handlers.go 9.6 KB

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