handlers.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "strings"
  8. "time"
  9. "github.com/bwmarrin/discordgo"
  10. "github.com/fatih/color"
  11. )
  12. type fileItem struct {
  13. Link string
  14. Filename string
  15. Time time.Time
  16. }
  17. //#region Events
  18. func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
  19. handleMessage(m.Message, false, false)
  20. }
  21. func messageUpdate(s *discordgo.Session, m *discordgo.MessageUpdate) {
  22. if m.EditedTimestamp != nil {
  23. handleMessage(m.Message, true, false)
  24. }
  25. }
  26. func handleMessage(m *discordgo.Message, edited bool, history bool) int64 {
  27. // Ignore own messages unless told not to
  28. if m.Author.ID == botUser.ID && !config.ScanOwnMessages {
  29. return -1
  30. }
  31. if !history && !edited {
  32. timeLastMessage = time.Now()
  33. }
  34. // Admin Channel
  35. if isAdminChannelRegistered(m.ChannelID) {
  36. m = fixMessage(m)
  37. // Log
  38. sendLabel := fmt.Sprintf("%s in \"%s\"#%s",
  39. getUserIdentifier(*m.Author),
  40. getGuildName(m.GuildID), getChannelName(m.ChannelID),
  41. )
  42. content := m.Content
  43. if len(m.Attachments) > 0 {
  44. content = content + fmt.Sprintf(" (%d attachments)", len(m.Attachments))
  45. }
  46. if edited {
  47. log.Println(lg("Message", "ADMIN CHANNEL", color.CyanString, "Edited [%s]: %s", sendLabel, content))
  48. } else {
  49. log.Println(lg("Message", "ADMIN CHANNEL", color.CyanString, "Message [%s]: %s", sendLabel, content))
  50. }
  51. }
  52. // Registered Channel
  53. if channelConfig := getSource(m); channelConfig != emptyConfig {
  54. // Ignore bots if told to do so
  55. if m.Author.Bot && *channelConfig.IgnoreBots {
  56. return -1
  57. }
  58. // Ignore if told so by config
  59. if (!history && !*channelConfig.Enabled) || (edited && !*channelConfig.ScanEdits) {
  60. return -1
  61. }
  62. m = fixMessage(m)
  63. // Log
  64. if config.MessageOutput {
  65. sendLabel := fmt.Sprintf("%s in \"%s\"#%s",
  66. getUserIdentifier(*m.Author),
  67. getGuildName(m.GuildID), getChannelName(m.ChannelID),
  68. )
  69. content := m.Content
  70. if len(m.Attachments) > 0 {
  71. content = content + fmt.Sprintf(" (%d attachments)", len(m.Attachments))
  72. }
  73. if !history {
  74. if edited {
  75. log.Println(lg("Message", "", color.CyanString, "Edited [%s]: %s", sendLabel, content))
  76. } else {
  77. log.Println(lg("Message", "", color.CyanString, "Message [%s]: %s", sendLabel, content))
  78. }
  79. }
  80. }
  81. // Log Messages to File
  82. if channelConfig.LogMessages != nil {
  83. if channelConfig.LogMessages.Destination != "" {
  84. logPath := channelConfig.LogMessages.Destination
  85. if *channelConfig.LogMessages.DestinationIsFolder == true {
  86. if !strings.HasSuffix(logPath, string(os.PathSeparator)) {
  87. logPath += string(os.PathSeparator)
  88. }
  89. err := os.MkdirAll(logPath, 0755)
  90. if err == nil {
  91. logPath += "Log_Messages"
  92. if *channelConfig.LogMessages.DivideLogsByServer == true {
  93. if m.GuildID == "" {
  94. ch, err := bot.State.Channel(m.ChannelID)
  95. if err == nil {
  96. if ch.Type == discordgo.ChannelTypeDM {
  97. logPath += " DM"
  98. } else if ch.Type == discordgo.ChannelTypeGroupDM {
  99. logPath += " GroupDM"
  100. } else {
  101. logPath += " Unknown"
  102. }
  103. } else {
  104. logPath += " Unknown"
  105. }
  106. } else {
  107. logPath += " SID_" + m.GuildID
  108. }
  109. }
  110. if *channelConfig.LogMessages.DivideLogsByChannel == true {
  111. logPath += " CID_" + m.ChannelID
  112. }
  113. if *channelConfig.LogMessages.DivideLogsByUser == true {
  114. logPath += " UID_" + m.Author.ID
  115. }
  116. }
  117. logPath += ".txt"
  118. }
  119. // Read
  120. currentLog, err := ioutil.ReadFile(logPath)
  121. currentLogS := ""
  122. if err == nil {
  123. currentLogS = string(currentLog)
  124. }
  125. canLog := true
  126. // Filter Duplicates
  127. if channelConfig.LogMessages.FilterDuplicates != nil {
  128. if *channelConfig.LogMessages.FilterDuplicates {
  129. if strings.Contains(currentLogS, fmt.Sprintf("[%s/%s/%s]", m.GuildID, m.ChannelID, m.ID)) {
  130. canLog = false
  131. }
  132. }
  133. }
  134. if canLog {
  135. // Writer
  136. f, err := os.OpenFile(logPath, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0600)
  137. if err != nil {
  138. log.Println(lg("Message", "", color.RedString, "[channelConfig.LogMessages] Failed to open log file:\t%s", err))
  139. f.Close()
  140. }
  141. defer f.Close()
  142. var newLine string
  143. // Prepend
  144. prefix := ""
  145. if channelConfig.LogMessages.Prefix != nil {
  146. prefix = *channelConfig.LogMessages.Prefix
  147. }
  148. // More Data
  149. additionalInfo := ""
  150. if channelConfig.LogMessages.UserData != nil {
  151. if *channelConfig.LogMessages.UserData == true {
  152. additionalInfo = fmt.Sprintf("[%s/%s/%s] \"%s\"#%s (%s) @ %s: ", m.GuildID, m.ChannelID, m.ID, m.Author.Username, m.Author.Discriminator, m.Author.ID, m.Timestamp)
  153. }
  154. }
  155. if len(m.Attachments) > 0 {
  156. additionalInfo += fmt.Sprintf("<%d ATTACHMENTS> ", len(m.Attachments))
  157. }
  158. // Append
  159. suffix := ""
  160. if channelConfig.LogMessages.Suffix != nil {
  161. suffix = *channelConfig.LogMessages.Suffix
  162. }
  163. // New Line
  164. contentFmt, err := m.ContentWithMoreMentionsReplaced(bot)
  165. if err == nil {
  166. newLine += "\n" + prefix + additionalInfo + contentFmt + suffix
  167. } else {
  168. newLine += "\n" + prefix + additionalInfo + m.Content + suffix
  169. }
  170. if _, err = f.WriteString(newLine); err != nil {
  171. log.Println(lg("Message", "", color.RedString, "[channelConfig.LogMessages] Failed to append file:\t%s", err))
  172. }
  173. }
  174. }
  175. }
  176. // Filters
  177. if channelConfig.Filters != nil {
  178. shouldAbort := false
  179. if channelConfig.Filters.AllowedPhrases != nil ||
  180. channelConfig.Filters.AllowedUsers != nil ||
  181. channelConfig.Filters.AllowedRoles != nil {
  182. shouldAbort = true
  183. if config.DebugOutput {
  184. log.Println(lg("Debug", "Message", color.YellowString,
  185. "%s Filter will be ignoring by default...",
  186. color.HiMagentaString("(FILTER)")))
  187. }
  188. }
  189. if channelConfig.Filters.BlockedPhrases != nil {
  190. for _, phrase := range *channelConfig.Filters.BlockedPhrases {
  191. if strings.Contains(m.Content, phrase) {
  192. shouldAbort = true
  193. if config.DebugOutput {
  194. log.Println(lg("Debug", "Message", color.YellowString,
  195. "%s blockedPhrases found \"%s\" in message, planning to abort...",
  196. color.HiMagentaString("(FILTER)"), phrase))
  197. }
  198. break
  199. }
  200. }
  201. }
  202. if channelConfig.Filters.AllowedPhrases != nil {
  203. for _, phrase := range *channelConfig.Filters.AllowedPhrases {
  204. if strings.Contains(m.Content, phrase) {
  205. shouldAbort = false
  206. if config.DebugOutput {
  207. log.Println(lg("Debug", "Message", color.YellowString,
  208. "%s allowedPhrases found \"%s\" in message, planning to process...",
  209. color.HiMagentaString("(FILTER)"), phrase))
  210. }
  211. break
  212. }
  213. }
  214. }
  215. if channelConfig.Filters.BlockedUsers != nil {
  216. if stringInSlice(m.Author.ID, *channelConfig.Filters.BlockedUsers) {
  217. shouldAbort = true
  218. if config.DebugOutput {
  219. log.Println(lg("Debug", "Message", color.YellowString,
  220. "%s blockedUsers caught %s, planning to abort...",
  221. color.HiMagentaString("(FILTER)"), m.Author.ID))
  222. }
  223. }
  224. }
  225. if channelConfig.Filters.AllowedUsers != nil {
  226. if stringInSlice(m.Author.ID, *channelConfig.Filters.AllowedUsers) {
  227. shouldAbort = false
  228. if config.DebugOutput {
  229. log.Println(lg("Debug", "Message", color.YellowString,
  230. "%s allowedUsers caught %s, planning to process...",
  231. color.HiMagentaString("(FILTER)"), m.Author.ID))
  232. }
  233. }
  234. }
  235. if channelConfig.Filters.BlockedRoles != nil {
  236. member := m.Member
  237. if member == nil {
  238. member, _ = bot.GuildMember(m.GuildID, m.Author.ID)
  239. }
  240. if member != nil {
  241. for _, role := range member.Roles {
  242. if stringInSlice(role, *channelConfig.Filters.BlockedRoles) {
  243. shouldAbort = true
  244. if config.DebugOutput {
  245. log.Println(lg("Debug", "Message", color.YellowString,
  246. "%s blockedRoles caught %s, planning to abort...",
  247. color.HiMagentaString("(FILTER)"), role))
  248. }
  249. break
  250. }
  251. }
  252. }
  253. }
  254. if channelConfig.Filters.AllowedRoles != nil {
  255. member := m.Member
  256. if member == nil {
  257. member, _ = bot.GuildMember(m.GuildID, m.Author.ID)
  258. }
  259. if member != nil {
  260. for _, role := range member.Roles {
  261. if stringInSlice(role, *channelConfig.Filters.AllowedRoles) {
  262. shouldAbort = false
  263. if config.DebugOutput {
  264. log.Println(lg("Debug", "Message", color.YellowString,
  265. "%s allowedRoles caught %s, planning to allow...",
  266. color.HiMagentaString("(FILTER)"), role))
  267. }
  268. break
  269. }
  270. }
  271. }
  272. }
  273. // Abort
  274. if shouldAbort {
  275. if config.DebugOutput {
  276. log.Println(lg("Debug", "Message", color.YellowString,
  277. "%s Filter decided to ignore message...",
  278. color.HiMagentaString("(FILTER)")))
  279. }
  280. return -1
  281. }
  282. }
  283. // Process Files
  284. var downloadCount int64
  285. files := getFileLinks(m)
  286. for _, file := range files {
  287. if file.Link == "" {
  288. continue
  289. }
  290. if config.DebugOutput && !history {
  291. log.Println(lg("Debug", "Message", color.CyanString, "FOUND FILE: "+file.Link))
  292. }
  293. status := handleDownload(
  294. downloadRequestStruct{
  295. InputURL: file.Link,
  296. Filename: file.Filename,
  297. Path: channelConfig.Destination,
  298. Message: m,
  299. FileTime: file.Time,
  300. HistoryCmd: history,
  301. EmojiCmd: false,
  302. StartTime: time.Now(),
  303. })
  304. if status.Status == downloadSuccess {
  305. downloadCount++
  306. }
  307. }
  308. return downloadCount
  309. }
  310. return -1
  311. }
  312. //#endregion