statistics.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. from datetime import datetime
  2. from commands.common import CommandHelpers as CH, StatisticsHelpers
  3. bold = "\x02"
  4. italic = "\x1D"
  5. underline = "\x1F"
  6. reverse = "\x16" # swap background and foreground colors ("reverse video")
  7. reset = "\x0F"
  8. blue = "\x0302"
  9. green = "\x0303"
  10. red = "\x0304"
  11. grey = "\x0314"
  12. def do_command(self, connection, event):
  13. cmdtype, trigger, command, replyto = CH.disect_command(self, event)
  14. # Do nothing if there is no command.
  15. if not command:
  16. return
  17. try:
  18. command.split()[0]
  19. except:
  20. return
  21. # Do noting if the games channel function is off and it's a channel message.
  22. if not self.db.one("SELECT statistics_commands FROM channels WHERE name='" + event.target + "' AND network='" + self.network + "'") and not event.target == connection.get_nickname():
  23. return
  24. if command == "cmd" or command == "cmds" or command == "commands":
  25. if cmdtype == "cmd":
  26. connection.privmsg(replyto, grey + "Statistics commands: " + CH.ccc(self, "seen") + CH.ccc(self, "joins") + CH.ccc(self, "kicks") + CH.ccc(self, "messages") + CH.ccc(self, "actions") + CH.ccc(self, "notices")[:-2] + ".")
  27. elif command.split()[0] == "joins" or command.split()[0] == "kicks" or command.split()[0] == "messages" or command.split()[0] == "actions" or command.split()[0] == "notices":
  28. if cmdtype == "help": #Display help text.
  29. if len(command.split()) is not 1:
  30. return
  31. connection.privmsg(replyto, "Display amount of " + command.split()[0] + " of user and channel. Channel and user optional.")
  32. connection.privmsg(replyto, grey + "Usage: " + blue + self.cmdchar + command.split()[0] + " " + reset + italic + "channel user")
  33. elif cmdtype == "cmd":
  34. # Parse user input
  35. user = event.source.nick
  36. channel = None
  37. channelonly= False
  38. if not connection.get_nickname() == event.target: # Channel message.
  39. channel = event.target
  40. if len(command.split()) == 1: # Command contains only !joins.
  41. user = event.source.nick
  42. elif len(command.split()) == 2: # Command has one argument.
  43. if command.split()[1] in self.channels:
  44. channel = command.split()[1]
  45. if connection.get_nickname() == event.target: # Private message.
  46. channelonly = True
  47. else:
  48. user = trigger.split()[1]
  49. elif len(command.split()) == 3: # Command has two arguments.
  50. if not command.split()[1] in self.channels: # Bot does not inhabit requested channel.
  51. if not command.split()[2] in self.channels: # User did not revert channel and user in command syntax.
  52. connection.action(replyto, "does not inhabit " + red + command.split()[1] + reset + ".")
  53. return
  54. else: # User reverted user and channel in command syntax.
  55. user = trigger.split()[1]
  56. channel = command.split()[2]
  57. else: # Bot does inhabit requested channel.
  58. user = trigger.split()[2]
  59. channel = trigger.split()[1]
  60. elif len(command.split()) < 5: # To many arguments
  61. connection.privmsg(replyto, "To many arguments. For help type " + blue + self.helpchar + "joins" + reset + ".")
  62. return
  63. if command.split()[0] == "joins":
  64. if channel: # User and channel.
  65. userstat = str(sum(self.db.all("SELECT " + command.split()[0] + " FROM " + command.split()[0] + " WHERE channel_network='" + self.network + "' AND LOWER(\"user\")=LOWER('" + user + "') AND user_network='" + self.network + "'")))
  66. userchannelstat = str(self.db.one("SELECT " + command.split()[0] + " FROM " + command.split()[0] + " WHERE LOWER(channel)=LOWER('" + channel + "') AND channel_network='" + self.network + "' AND LOWER(\"user\")=LOWER('" + user + "') AND user_network='" + self.network + "'"))
  67. channelstat = str(sum(self.db.all("SELECT " + command.split()[0] + " FROM " + command.split()[0] + " WHERE LOWER(channel)=LOWER('" + channel + "') AND channel_network='" + self.network + "' AND user_network='" + self.network + "'")))
  68. if userchannelstat == "None":
  69. userchannelstat = "0"
  70. if channelonly:
  71. connection.privmsg(replyto, red + channel + reset + " has " + green + channelstat + reset + " " + command.split()[0] + reset + " in total.")
  72. elif userstat == "0" and not channelonly: # No user joins on record.
  73. connection.action(replyto, "has no record of any joins by " + red + user + reset + " in " + red + channel + reset + ".")
  74. else: # User joins on record.
  75. connection.privmsg(replyto, red + user + reset + " has " + green + userstat + reset + " " + command.split()[0] + ". Of which " + green + userchannelstat + reset + " have been in " + red + channel + reset + ", that has " + green + channelstat + reset + " " + command.split()[0] + reset + " in total.")
  76. else: # Only user.
  77. userstat = str(sum(self.db.all("SELECT " + command.split()[0] + " FROM " + command.split()[0] + " WHERE channel_network='" + self.network + "' AND LOWER(\"user\")=LOWER('" + user + "') AND user_network='" + self.network + "'")))
  78. if userstat == "0": # No statistics on user.
  79. connection.action(replyto, "has no record of any joins by " + red + user + reset + ".")
  80. else: # Got statistics on user.
  81. connection.privmsg(replyto, red + user + reset + " has " + green + userstat + reset + " " + command.split()[0] + " in channels I monitor.")
  82. elif command.split()[0] == "kicks":
  83. if channel: # User and channel.
  84. try:
  85. givenkicks, receivedkicks = self.db.one("SELECT given, received FROM " + command.split()[0] + " WHERE LOWER(channel)=LOWER('" + channel + "') AND channel_network='" + self.network + "' AND LOWER(\"user\")=LOWER('" + user + "') AND user_network='" + self.network + "'")
  86. except:
  87. givenkicks = 0
  88. receivedkicks = 0
  89. if channelonly:
  90. connection.privmsg(replyto, red + channel + reset + " has " + green + channelstat + reset + " " + command.split()[0] + reset + " in total.")
  91. elif givenkicks == 0 and receivedkicks == 0: # No kicks on record.
  92. connection.action(replyto, "has no record of any kicks for " + red + user + reset + " in " + red + channel + reset + ".")
  93. else: # Kciks on record.
  94. channelkicks = self.db.all("SELECT given FROM " + command.split()[0] + " WHERE LOWER(channel)=LOWER('" + channel + "') AND channel_network='" + self.network + "'")
  95. connection.privmsg(replyto, red + user + reset + " has kicked " + green + str(givenkicks) + reset + " and been kicked " + green + str(receivedkicks) + reset + " times in " + red + channel + reset + ", where were " + green + str(sum(channelkicks)) + reset + " kicks in total.")
  96. else: # Only user.
  97. userstat = self.db.all("SELECT given, received FROM kicks WHERE LOWER(\"user\")=LOWER('" + user + "') AND user_network='" + self.network + "'")
  98. kicksgiven = 0
  99. kicksreceived = 0
  100. for record in userstat:
  101. kicksgiven += record[0]
  102. kicksreceived += record[1]
  103. if kicksgiven == 0 and kicksreceived == 0:
  104. connection.action(replyto, red + user + reset + " has no record of any kicks for " + red + user + reset + " in " + red + channel + reset + ".")
  105. else:
  106. connection.privmsg(replyto, red + user + reset + " has given " + green + str(kicksgiven) + reset + " and received " + green + str(kicksreceived) + reset + " kicks")
  107. elif command.split()[0] == "messages" or command.split()[0] == "actions" or command.split()[0] == "notices":
  108. userstat = self.db.all("SELECT " + command.split()[0] + ", " + command.split()[0] + "_words, " + command.split()[0] + "_characters FROM messages WHERE LOWER(\"user\")=LOWER('" + user + "') AND user_network='" + self.network + "'")
  109. print(userstat[0])
  110. userrecord = False
  111. for record in userstat:
  112. if not record[0] == 0:
  113. userrecord = True
  114. if not userrecord:
  115. if command.split()[0] == "messages":
  116. connection.action(replyto, "has no record of " + red + user + reset + " speaking.")
  117. return
  118. if command.split()[0] == "actions":
  119. connection.action(replyto, "has no record of " + red + user + reset + " acting.")
  120. return
  121. if command.split()[0] == "notices":
  122. connection.action(replyto, "has not noticed " + red + user + reset + ".")
  123. return
  124. messages, words, characters = StatisticsHelpers.add_message_stats(userstat)
  125. message = "Totals of " + red + user + " " + green + str(messages) + reset + " " + blue + command.split()[0] + reset + ", " + green + str(words) + reset + " words, " + green + str(characters) + reset + " characters."
  126. if channel: # User and channel.
  127. userchanstat = self.db.one("SELECT " + command.split()[0] + ", " + command.split()[0] + "_words, " + command.split()[0] + "_characters FROM messages WHERE lower(channel)=lower('" + channel + "') AND channel_network='" + self.network + "' AND lower(\"user\")=lower('" + user + "') AND user_network='" + self.network + "'")
  128. chanstat = self.db.all("SELECT " + command.split()[0] + ", " + command.split()[0] + "_words, " + command.split()[0] + "_characters FROM messages WHERE lower(channel)=lower('" + channel + "') AND channel_network='" + self.network + "'")
  129. if not userchanstat[0] == 0:
  130. message += " " + red + user + reset + " in " + red + channel + " " + green + str(userchanstat[0]) + reset + " " + blue + command.split()[0] + reset + ", " + green + str(userchanstat[1]) + reset + " words, " + green + str(userchanstat[2]) + reset + " chars."
  131. channelrecord = False
  132. for record in chanstat:
  133. if not record[0] == 0:
  134. channelrecord = True
  135. if channelrecord:
  136. messages, words, characters = StatisticsHelpers.add_message_stats(chanstat)
  137. message += " Total in " + red + channel + " " + green + str(messages) + reset + " " + blue + command.split()[0] + reset + ", " + green + str(words) + reset + " wrd, " + green + str(characters) + reset + " chr."
  138. connection.privmsg(replyto, message)
  139. elif command.split()[0] == "seen":
  140. if cmdtype == "help": #Display help text.
  141. if len(command.split()) is not 1:
  142. return
  143. connection.privmsg(replyto, "Report the last sighting of a user.")
  144. connection.privmsg(replyto, grey + "Usage: " + blue + self.cmdchar + command.split()[0] + " " + reset + italic + "user")
  145. elif cmdtype == "cmd":
  146. if len(command.split()) == 1:
  147. connection.privmsg(replyto, "I am seeing you right now. For help type " + blue + self.helpchar + reset + ".")
  148. elif len(command.split()) == 2:
  149. if not self.db.one("SELECT last_act_type FROM users WHERE LOWER(name)='" + command.split()[1] + "' AND network='" + self.network + "'"):
  150. connection.action(replyto, "has never seen " + red + trigger.split()[1] + reset + ".")
  151. elif command.split()[1] == event.source.nick.lower():
  152. connection.action(replyto, "holds up a mirror to " + event.source.nick + ".")
  153. else:
  154. record = self.db.one("SELECT last_act_type, last_act_datetime, last_act_channel, last_act, last_act_auxiliary, away, away_reason FROM users WHERE LOWER(name)='" + command.split()[1] + "' AND network='" + self.network + "'")
  155. if command.split()[1] == connection.get_nickname().lower():
  156. action = "last action was "
  157. else:
  158. action = "last saw " + red + trigger.split()[1] + reset + " "
  159. if record[0] == "nick":
  160. action += "changing nickname to " + red + record[3]
  161. elif record[0] == "join":
  162. action += "joining " + red + record[2]
  163. elif record[0] == "kick":
  164. if record[4]:
  165. action += "kicking " + red + record[4] + reset + " for " + green + record[3]
  166. else:
  167. action += "kicking " + red + record[3]
  168. elif record[0] == "kicked":
  169. if record[4]:
  170. action += "being kicked by " + red + record[3] + reset + " for " + green + record[4]
  171. else:
  172. action += "being kicked by " + red + record[3]
  173. elif record[0] == "mode":
  174. action += "changing modes on " + red + record[3]
  175. elif record[0] == "part":
  176. action += "parting " + red + record[2]
  177. if record[3]:
  178. action += reset + " for " + record[3]
  179. elif record[0] == "quit":
  180. action += "disconnecting"
  181. if record[3]:
  182. action += " due to " + green + record[3]
  183. elif record[0] == "topic":
  184. action += "changing the topic of " + red + record[2] + reset + " to " + green + record[3]
  185. elif record[0] == "msg":
  186. action += "posting " + green + record[3] + reset + " to " + red + record[2]
  187. elif record[0] == "notice":
  188. action += "posting the notice " + green + record[3] + " to " + red + record[2]
  189. elif record[0] == "action":
  190. action += green + record[3] + reset + " in " + red + record[2]
  191. else:
  192. connection.privmsg(replyto, "Last stored action unsupported by command code.")
  193. return
  194. action += reset + ", "
  195. differential = datetime.now() - record[1]
  196. if differential.seconds < 5: # Less then 5 seconds.
  197. action += blue + "right now."
  198. elif differential.seconds < 20: # Less then 20 seconds.
  199. action += blue + "just now."
  200. elif differential.seconds < 60: # Less then a minute.
  201. action += green + str(differential.seconds) + blue + " seconds " + reset + "ago."
  202. elif differential.seconds / 60 == 1: # 1 minute.
  203. action += green + "1 " + blue + "minute " + reset + "ago."
  204. elif int(differential.seconds / 60) < 60: # Less then an hour.
  205. action += green + str(int(differential.seconds / 60)) + blue + " minutes " + reset + "ago."
  206. elif int(differential.seconds / 60) == 60: # 1 hour.
  207. action += green + "1 " + blue + "hour " + reset + "ago."
  208. elif int(differential.seconds / 3600) < 24 : # Less then a day.
  209. remaining_seconds = int(differential.seconds - int(differential.seconds / 3600) * 3600)
  210. action += green + str(int(differential.seconds / 3600)) + blue + " hours" + reset + " and " + str(int(remaining_seconds / 60)) + " minutes ago."
  211. elif int(differential.seconds / 3600) == 24 : # 1 day.
  212. action += green + "1 " + blue + "day " + reset + "ago."
  213. elif differential.days < 7: # Less then a week.
  214. remaining = differential - datetime.timedelta(days=differential.days)
  215. action += green + str(differential.days) + blue + " days " + reset + "and " + str(int(remaining.seconds / 3600)) + " hours ago."
  216. elif differential.days < 365: # Less then a year.
  217. action += green + str(differential.days) + blue + " days " + reset + "ago."
  218. elif differential.days < 365: # Less then 5 years.
  219. remaining_days = int(int(differential.days / 365) * 365)
  220. remaining = differential - datetime.timedelta(days=remaining_days)
  221. action += green + str(int(differential.days / 365)) + blue + " years " + reset + "and " + str(remaining.days) + " days."
  222. else: # More then 5 years.
  223. action += green + str(int(differential.days / 365)) + blue + " years ago."
  224. connection.action(replyto, action)
  225. if record[5]:
  226. if record[6]:
  227. connection.privmsg(replyto, red + trigger.split()[1] + reset + " is away " + green + record[6] + ".")
  228. else:
  229. connection.privmsg(replyto, red + trigger.split()[1] + reset + " is away.")
  230. else: # Too many arguments.
  231. connection.privmsg(replyto, "Too many arguments. For help type " + blue + self.helpchar + "seen" + reset + ".")