handlers.go 9.6 KB

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