1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438 |
- package main
- import (
- "bufio"
- "encoding/json"
- "log"
- "os"
- "runtime"
- "strings"
- "github.com/bwmarrin/discordgo"
- "github.com/fatih/color"
- "github.com/muhammadmuzzammil1998/jsonc"
- "gopkg.in/ini.v1"
- )
- var (
- config = defaultConfiguration()
- )
- //#region Config, Credentials
- var (
- placeholderToken string = "REPLACE_WITH_YOUR_TOKEN_OR_DELETE_LINE"
- placeholderEmail string = "REPLACE_WITH_YOUR_EMAIL_OR_DELETE_LINE"
- placeholderPassword string = "REPLACE_WITH_YOUR_PASSWORD_OR_DELETE_LINE"
- )
- type configurationCredentials struct {
- // Login
- Token string `json:"token,omitempty"` // required for bot token (this or login)
- Email string `json:"email,omitempty"` // required for login (this or token)
- Password string `json:"password,omitempty"` // required for login (this or token)
- // APIs
- TwitterUsername string `json:"twitterUsername,omitempty"` // optional
- TwitterPassword string `json:"twitterPassword,omitempty"` // optional
- InstagramUsername string `json:"instagramUsername,omitempty"` // optional
- InstagramPassword string `json:"instagramPassword,omitempty"` // optional
- FlickrApiKey string `json:"flickrApiKey,omitempty"` // optional
- }
- //#endregion
- //#region Config, Main
- // defConfig_ = Config Default
- // Needed for settings used without redundant nil checks, and settings defaulting + creation
- var (
- defConfig_Debug bool = false
- defConfig_CommandPrefix string = "ddg "
- defConfig_ScanOwnMessages bool = false
- defConfig_GithubUpdateChecking bool = true
- // Appearance
- defConfig_PresenceEnabled bool = true
- defConfig_PresenceStatus string = string(discordgo.StatusIdle)
- defConfig_PresenceType discordgo.GameType = discordgo.GameTypeGame
- defConfig_ReactWhenDownloaded bool = false
- defConfig_InflateDownloadCount int64 = 0
- // These are only defaults to "fix" when loading settings for when people put stupid values
- defConfig_ProcessLimit int = 32
- defConfig_DiscordTimeout int = 180
- defConfig_DownloadTimeout int = 60
- defConfig_DownloadRetryMax int = 3
- defConfig_CheckupRate int = 30
- defConfig_ConnectionCheckRate int = 5
- defConfig_PresenceRefreshRate int = 3
- defConfig_FilenameDateFormat string = "2006-01-02_15-04-05"
- defConfig_FilenameFormat string = "{{date}} {{file}}"
- defConfig_HistoryMaxJobs int = 3
- )
- func defaultConfiguration() configuration {
- return configuration{
- // Logins
- Credentials: configurationCredentials{
- Token: placeholderToken,
- Email: placeholderEmail,
- Password: placeholderPassword,
- },
- // Owner Settings
- Admins: []string{},
- AdminChannels: []configurationAdminChannel{},
- // Program Settings
- ProcessLimit: defConfig_ProcessLimit,
- Debug: defConfig_Debug,
- BackupDatabaseOnStart: false,
- WatchSettings: true,
- SettingsOutput: true,
- MessageOutput: true,
- MessageOutputHistory: false,
- DiscordLogLevel: discordgo.LogError,
- DiscordTimeout: defConfig_DiscordTimeout,
- DownloadTimeout: defConfig_DownloadTimeout,
- DownloadRetryMax: defConfig_DownloadRetryMax,
- ExitOnBadConnection: false,
- GithubUpdateChecking: defConfig_GithubUpdateChecking,
- CommandPrefix: defConfig_CommandPrefix,
- ScanOwnMessages: defConfig_ScanOwnMessages,
- AllowGeneralCommands: true,
- InflateDownloadCount: &defConfig_InflateDownloadCount,
- EuropeanNumbers: false,
- CheckupRate: defConfig_CheckupRate,
- ConnectionCheckRate: defConfig_ConnectionCheckRate,
- PresenceRefreshRate: defConfig_PresenceRefreshRate,
- // Source Setup Defaults
- Save: true,
- AllowCommands: true,
- ScanEdits: true,
- IgnoreBots: true,
- SendErrorMessages: false,
- SendFileToChannel: "",
- SendFileToChannels: []string{},
- SendFileDirectly: true,
- SendFileCaption: "",
- FilenameDateFormat: defConfig_FilenameDateFormat,
- FilenameFormat: defConfig_FilenameFormat,
- // Appearance
- PresenceEnabled: defConfig_PresenceEnabled,
- PresenceStatus: defConfig_PresenceStatus,
- PresenceType: defConfig_PresenceType,
- ReactWhenDownloaded: defConfig_ReactWhenDownloaded,
- ReactWhenDownloadedHistory: false,
- HistoryTyping: true,
- // History
- HistoryMaxJobs: defConfig_HistoryMaxJobs,
- AutoHistory: false,
- AutoHistoryBefore: "",
- AutoHistorySince: "",
- SendHistoryStatus: true,
- SendAutoHistoryStatus: false,
- // Rules for Saving
- DivideByYear: false,
- DivideByMonth: false,
- DivideByServer: false,
- DivideByChannel: false,
- DivideByUser: false,
- DivideByType: true,
- DivideFoldersUseID: false,
- SaveImages: true,
- SaveVideos: true,
- SaveAudioFiles: true,
- SaveTextFiles: false,
- SaveOtherFiles: false,
- SavePossibleDuplicates: true,
- Filters: &configurationSourceFilters{
- BlockedExtensions: &[]string{
- ".htm",
- ".html",
- ".php",
- ".exe",
- ".dll",
- ".bin",
- ".cmd",
- ".sh",
- ".py",
- ".jar",
- },
- BlockedPhrases: &[]string{},
- },
- Duplo: false,
- DuploThreshold: 0,
- }
- }
- type configuration struct {
- Constants map[string]string `json:"_constants,omitempty"`
- // Logins
- Credentials configurationCredentials `json:"credentials"` // required
- // Owner Settings
- Admins []string `json:"admins"` // optional
- AdminChannels []configurationAdminChannel `json:"adminChannels"` // optional
- // Program Settings
- ProcessLimit int `json:"processLimit,omitempty"` // optional, defaults
- Debug bool `json:"debug,omitempty"` // optional, defaults
- BackupDatabaseOnStart bool `json:"backupDatabaseOnStart,omitempty"` // optional, defaults
- WatchSettings bool `json:"watchSettings,omitempty"` // optional, defaults
- SettingsOutput bool `json:"settingsOutput,omitempty"` // optional, defaults
- MessageOutput bool `json:"messageOutput,omitempty"` // optional, defaults
- MessageOutputHistory bool `json:"messageOutputHistory,omitempty"` // optional, defaults
- DiscordLogLevel int `json:"discordLogLevel,omitempty"` // optional, defaults
- DiscordTimeout int `json:"discordTimeout,omitempty"` // optional, defaults
- DownloadTimeout int `json:"downloadTimeout,omitempty"` // optional, defaults
- DownloadRetryMax int `json:"downloadRetryMax,omitempty"` // optional, defaults
- ExitOnBadConnection bool `json:"exitOnBadConnection,omitempty"` // optional, defaults
- GithubUpdateChecking bool `json:"githubUpdateChecking,omitempty"` // optional, defaults
- CommandPrefix string `json:"commandPrefix,omitempty"` // optional, defaults
- ScanOwnMessages bool `json:"scanOwnMessages,omitempty"` // optional, defaults
- AllowGeneralCommands bool `json:"allowGeneralCommands,omitempty"` // optional, defaults
- InflateDownloadCount *int64 `json:"inflateDownloadCount,omitempty"` // optional, defaults to 0 if undefined
- EuropeanNumbers bool `json:"europeanNumbers,omitempty"` // optional, defaults
- CheckupRate int `json:"checkupRate,omitempty"` // optional, defaults
- ConnectionCheckRate int `json:"connectionCheckRate,omitempty"` // optional, defaults
- PresenceRefreshRate int `json:"presenceRefreshRate,omitempty"` // optional, defaults
- // Source Setup Defaults
- Save bool `json:"save,omitempty"` // optional, defaults
- AllowCommands bool `json:"allowCommands,omitempty"` // optional, defaults
- ScanEdits bool `json:"scanEdits,omitempty"` // optional, defaults
- IgnoreBots bool `json:"ignoreBots,omitempty"` // optional, defaults
- SendErrorMessages bool `json:"sendErrorMessages,omitempty"` // optional, defaults
- SendFileToChannel string `json:"sendFileToChannel,omitempty"` // optional, defaults
- SendFileToChannels []string `json:"sendFileToChannels,omitempty"` // optional, defaults
- SendFileDirectly bool `json:"sendFileDirectly,omitempty"` // optional, defaults
- SendFileCaption string `json:"sendFileCaption,omitempty"` // optional
- FilenameDateFormat string `json:"filenameDateFormat,omitempty"` // optional, defaults
- FilenameFormat string `json:"filenameFormat,omitempty"` // optional, defaults
- // Appearance
- PresenceEnabled bool `json:"presenceEnabled,omitempty"` // optional, defaults
- PresenceStatus string `json:"presenceStatus,omitempty"` // optional, defaults
- PresenceType discordgo.GameType `json:"presenceType,omitempty"` // optional, defaults
- PresenceLabel *string `json:"presenceLabel,omitempty"` // optional, unused if undefined
- PresenceDetails *string `json:"presenceDetails,omitempty"` // optional, unused if undefined
- PresenceState *string `json:"presenceState,omitempty"` // optional, unused if undefined
- ReactWhenDownloaded bool `json:"reactWhenDownloaded,omitempty"` // optional, defaults
- ReactWhenDownloadedEmoji *string `json:"reactWhenDownloadedEmoji,omitempty"` // optional
- ReactWhenDownloadedHistory bool `json:"reactWhenDownloadedHistory,omitempty"` // optional, defaults
- HistoryTyping bool `json:"historyTyping,omitempty"` // optional, defaults
- EmbedColor *string `json:"embedColor,omitempty"` // optional, defaults to role if undefined, then defaults random if no role color
- // History
- HistoryMaxJobs int `json:"historyMaxJobs,omitempty"` // optional, defaults
- AutoHistory bool `json:"autoHistory,omitempty"` // optional, defaults
- AutoHistoryBefore string `json:"autoHistoryBefore,omitempty"` // optional
- AutoHistorySince string `json:"autoHistorySince,omitempty"` // optional
- SendAutoHistoryStatus bool `json:"sendAutoHistoryStatus,omitempty"` // optional, defaults
- SendHistoryStatus bool `json:"sendHistoryStatus,omitempty"` // optional, defaults
- // Rules for Saving
- DivideByYear bool `json:"divideByYear,omitempty"` // defaults
- DivideByMonth bool `json:"divideByMonth,omitempty"` // defaults
- DivideByServer bool `json:"divideByServer,omitempty"` // defaults
- DivideByChannel bool `json:"divideByChannel,omitempty"` // defaults
- DivideByUser bool `json:"divideByUser,omitempty"` // defaults
- DivideByType bool `json:"divideByType,omitempty"` // defaults
- DivideFoldersUseID bool `json:"divideFoldersUseID,omitempty"` // defaults
- SaveImages bool `json:"saveImages,omitempty"` // defaults
- SaveVideos bool `json:"saveVideos,omitempty"` // defaults
- SaveAudioFiles bool `json:"saveAudioFiles,omitempty"` // defaults
- SaveTextFiles bool `json:"saveTextFiles,omitempty"` // defaults
- SaveOtherFiles bool `json:"saveOtherFiles,omitempty"` // defaults
- SavePossibleDuplicates bool `json:"savePossibleDuplicates,omitempty"` // defaults
- Filters *configurationSourceFilters `json:"filters,omitempty"` // optional
- Duplo bool `json:"duplo,omitempty"` // optional, defaults
- DuploThreshold float64 `json:"duploThreshold,omitempty"` // optional, defaults
- // Sources
- All *configurationSource `json:"all,omitempty"`
- AllBlacklistUsers *[]string `json:"allBlacklistUsers,omitempty"`
- AllBlacklistServers *[]string `json:"allBlacklistServers,omitempty"`
- AllBlacklistCategories *[]string `json:"allBlacklistCategories,omitempty"`
- AllBlacklistChannels *[]string `json:"allBlacklistChannels,omitempty"`
- Users []configurationSource `json:"users,omitempty"`
- Servers []configurationSource `json:"servers,omitempty"`
- Categories []configurationSource `json:"categories,omitempty"`
- Channels []configurationSource `json:"channels,omitempty"`
- }
- type constStruct struct {
- Constants map[string]string `json:"_constants,omitempty"`
- }
- //#endregion
- //#region Config, Sources
- // Needed for settings used without redundant nil checks, and settings defaulting + creation
- var (
- defSource_Enabled bool = true
- )
- type configurationSource struct {
- // ~
- UserID string `json:"user,omitempty"` // used for config.Users
- UserIDs *[]string `json:"users,omitempty"` // ---> alternative to UserID
- ServerID string `json:"server,omitempty"` // used for config.Servers
- ServerIDs *[]string `json:"servers,omitempty"` // ---> alternative to ServerID
- ServerBlacklist *[]string `json:"serverBlacklist,omitempty"` // for server.ServerID & server.ServerIDs
- CategoryID string `json:"category,omitempty"` // used for config.Categories
- CategoryIDs *[]string `json:"categories,omitempty"` // ---> alternative to CategoryID
- CategoryBlacklist *[]string `json:"categoryBlacklist,omitempty"` // for server.CategoryID & server.CategoryIDs
- ChannelID string `json:"channel,omitempty"` // used for config.Channels
- ChannelIDs *[]string `json:"channels,omitempty"` // ---> alternative to ChannelID
- Destination string `json:"destination"` // required
- // Setup
- Enabled *bool `json:"enabled"` // optional, defaults
- Save *bool `json:"save"` // optional, defaults
- AllowCommands *bool `json:"allowCommands,omitempty"` // optional, defaults
- ScanEdits *bool `json:"scanEdits,omitempty"` // optional, defaults
- IgnoreBots *bool `json:"ignoreBots,omitempty"` // optional, defaults
- SendErrorMessages *bool `json:"sendErrorMessages,omitempty"` // optional, defaults
- SendFileToChannel *string `json:"sendFileToChannel,omitempty"` // optional, defaults
- SendFileToChannels *[]string `json:"sendFileToChannels,omitempty"` // optional, defaults
- SendFileDirectly *bool `json:"sendFileDirectly,omitempty"` // optional, defaults
- SendFileCaption *string `json:"sendFileCaption,omitempty"` // optional
- FilenameDateFormat *string `json:"filenameDateFormat,omitempty"` // optional
- FilenameFormat *string `json:"filenameFormat,omitempty"` // optional
- // Appearance
- PresenceEnabled *bool `json:"presenceEnabled,omitempty"` // optional, defaults
- ReactWhenDownloaded *bool `json:"reactWhenDownloaded,omitempty"` // optional, defaults
- ReactWhenDownloadedEmoji *string `json:"reactWhenDownloadedEmoji,omitempty"` // optional, defaults
- ReactWhenDownloadedHistory *bool `json:"reactWhenDownloadedHistory,omitempty"` // optional, defaults
- BlacklistReactEmojis *[]string `json:"blacklistReactEmojis,omitempty"` // optional
- HistoryTyping *bool `json:"historyTyping,omitempty"` // optional, defaults
- EmbedColor *string `json:"embedColor,omitempty"` // optional, defaults to role if undefined, then defaults random if no role color
- // History
- AutoHistory *bool `json:"autoHistory,omitempty"` // optional
- AutoHistoryBefore *string `json:"autoHistoryBefore,omitempty"` // optional
- AutoHistorySince *string `json:"autoHistorySince,omitempty"` // optional
- SendAutoHistoryStatus *bool `json:"sendAutoHistoryStatus,omitempty"` // optional, defaults
- SendHistoryStatus *bool `json:"sendHistoryStatus,omitempty"` // optional, defaults
- // Rules for Saving
- DivideByYear *bool `json:"divideByYear,omitempty"` // optional, defaults
- DivideByMonth *bool `json:"divideByMonth,omitempty"` // optional, defaults
- DivideByServer *bool `json:"divideByServer,omitempty"` // optional, defaults
- DivideByChannel *bool `json:"divideByChannel,omitempty"` // optional, defaults
- DivideByUser *bool `json:"divideByUser,omitempty"` // optional, defaults
- DivideByType *bool `json:"divideByType,omitempty"` // optional, defaults
- DivideFoldersUseID *bool `json:"divideFoldersUseID,omitempty"` // optional, defaults
- SaveImages *bool `json:"saveImages,omitempty"` // optional, defaults
- SaveVideos *bool `json:"saveVideos,omitempty"` // optional, defaults
- SaveAudioFiles *bool `json:"saveAudioFiles,omitempty"` // optional, defaults
- SaveTextFiles *bool `json:"saveTextFiles,omitempty"` // optional, defaults
- SaveOtherFiles *bool `json:"saveOtherFiles,omitempty"` // optional, defaults
- SavePossibleDuplicates *bool `json:"savePossibleDuplicates,omitempty"` // optional, defaults
- Filters *configurationSourceFilters `json:"filters,omitempty"` // optional
- Duplo *bool `json:"duplo,omitempty"` // optional, defaults
- DuploThreshold *float64 `json:"duploThreshold,omitempty"` // optional, defaults
- // Misc Rules
- LogLinks *configurationSourceLog `json:"logLinks,omitempty"` // optional
- LogMessages *configurationSourceLog `json:"logMessages,omitempty"` // optional
- }
- type configurationSourceFilters struct {
- BlockedPhrases *[]string `json:"blockedPhrases,omitempty"` // optional
- AllowedPhrases *[]string `json:"allowedPhrases,omitempty"` // optional
- BlockedUsers *[]string `json:"blockedUsers,omitempty"` // optional
- AllowedUsers *[]string `json:"allowedUsers,omitempty"` // optional
- BlockedRoles *[]string `json:"blockedRoles,omitempty"` // optional
- AllowedRoles *[]string `json:"allowedRoles,omitempty"` // optional
- BlockedDomains *[]string `json:"blockedDomains,omitempty"` // optional
- AllowedDomains *[]string `json:"allowedDomains,omitempty"` // optional
- BlockedExtensions *[]string `json:"blockedExtensions,omitempty"` // optional
- AllowedExtensions *[]string `json:"allowedExtensions,omitempty"` // optional
- BlockedFilenames *[]string `json:"blockedFilenames,omitempty"` // optional
- AllowedFilenames *[]string `json:"allowedFilenames,omitempty"` // optional
- BlockedReactions *[]string `json:"blockedReactions,omitempty"` // optional
- AllowedReactions *[]string `json:"allowedReactions,omitempty"` // optional
- }
- var (
- defSourceLog_DestinationIsFolder bool = false
- defSourceLog_DivideLogsByServer bool = true
- defSourceLog_DivideLogsByChannel bool = true
- defSourceLog_DivideLogsByUser bool = false
- defSourceLog_DivideLogsByStatus bool = false
- defSourceLog_LogDownloads bool = true
- defSourceLog_LogFailures bool = true
- )
- type configurationSourceLog struct {
- Destination string `json:"destination"` // required
- DestinationIsFolder *bool `json:"destinationIsFolder,omitempty"` // optional, defaults
- DivideLogsByServer *bool `json:"divideLogsByServer,omitempty"` // optional, defaults
- DivideLogsByChannel *bool `json:"divideLogsByChannel,omitempty"` // optional, defaults
- DivideLogsByUser *bool `json:"divideLogsByUser,omitempty"` // optional, defaults
- DivideLogsByStatus *bool `json:"divideLogsByStatus,omitempty"` // optional, defaults
- LogDownloads *bool `json:"logDownloads,omitempty"` // optional, defaults
- LogFailures *bool `json:"logFailures,omitempty"` // optional, defaults
- FilterDuplicates *bool `json:"filterDuplicates,omitempty"` // optional, defaults
- Prefix *string `json:"prefix,omitempty"` // optional
- Suffix *string `json:"suffix,omitempty"` // optional
- UserData *bool `json:"userData,omitempty"` // optional, defaults
- }
- //#endregion
- //#region Config, Admin Channels
- var (
- adefConfig_LogProgram bool = false
- adefConfig_LogStatus bool = true
- adefConfig_LogErrors bool = true
- adefConfig_UnlockCommands bool = false
- )
- type configurationAdminChannel struct {
- ChannelID string `json:"channel"` // required
- ChannelIDs *[]string `json:"channels,omitempty"` // ---> alternative to ChannelID
- LogProgram *bool `json:"logProgram,omitempty"` // optional, defaults
- LogStatus *bool `json:"logStatus,omitempty"` // optional, defaults
- LogErrors *bool `json:"logErrors,omitempty"` // optional, defaults
- UnlockCommands *bool `json:"unlockCommands,omitempty"` // optional, defaults
- /* IDEAS / TODO:
- LogMessages *bool `json:"logMessages,omitempty"` // optional, defaults
- LogLinks *bool `json:"logLinks,omitempty"` // optional, defaults
- LogFiles *bool `json:"logFiles,omitempty"` // optional, defaults
- */
- }
- //#endregion
- //#region Management
- func loadConfig() error {
- // Determine json type
- if _, err := os.Stat(configFileBase + ".jsonc"); err == nil {
- configFile = configFileBase + ".jsonc"
- configFileC = true
- } else {
- configFile = configFileBase + ".json"
- configFileC = false
- }
- log.Println(lg("Settings", "loadConfig", color.YellowString, "Loading from \"%s\"...", configFile))
- // Load settings
- configContent, err := os.ReadFile(configFile)
- if err != nil {
- log.Println(lg("Settings", "loadConfig", color.HiRedString, "Failed to open file...\t%s", err))
- createConfig()
- properExit()
- } else {
- fixed := string(configContent)
- // Fix backslashes
- fixed = strings.ReplaceAll(fixed, "\\", "\\\\")
- for strings.Contains(fixed, "\\\\\\") {
- fixed = strings.ReplaceAll(fixed, "\\\\\\", "\\\\")
- }
- //TODO: Not even sure if this is realistic to do but would be nice to have line comma & trailing comma fixing
- // Parse
- newConfig := defaultConfiguration()
- if configFileC {
- err = jsonc.Unmarshal([]byte(fixed), &newConfig)
- } else {
- err = json.Unmarshal([]byte(fixed), &newConfig)
- }
- if err != nil {
- log.Println(lg("Settings", "loadConfig", color.HiRedString, "Failed to parse settings file...\t%s", err))
- log.Println(lg("Settings", "loadConfig", color.MagentaString, "Please ensure you're following proper JSON format syntax."))
- properExit()
- }
- // Constants
- if newConfig.Constants != nil {
- for key, value := range newConfig.Constants {
- if strings.Contains(fixed, key) {
- fixed = strings.ReplaceAll(fixed, key, value)
- }
- }
- // Re-parse
- newConfig = defaultConfiguration()
- if configFileC {
- err = jsonc.Unmarshal([]byte(fixed), &newConfig)
- } else {
- err = json.Unmarshal([]byte(fixed), &newConfig)
- }
- if err != nil {
- log.Println(lg("Settings", "loadConfig", color.HiRedString,
- "Failed to re-parse settings file after replacing constants...\t%s", err))
- log.Println(lg("Settings", "loadConfig", color.MagentaString, "Please ensure you're following proper JSON format syntax."))
- properExit()
- }
- newConfig.Constants = nil
- }
- config = newConfig
- // Source Defaults
- for i := 0; i < len(config.Channels); i++ {
- sourceDefault(&config.Channels[i])
- }
- for i := 0; i < len(config.Categories); i++ {
- sourceDefault(&config.Categories[i])
- }
- for i := 0; i < len(config.Servers); i++ {
- sourceDefault(&config.Servers[i])
- }
- for i := 0; i < len(config.Users); i++ {
- sourceDefault(&config.Users[i])
- }
- if config.All != nil {
- sourceDefault(config.All)
- }
- // Admin Channel Defaults
- for i := 0; i < len(config.AdminChannels); i++ {
- adminChannelDefault(&config.AdminChannels[i])
- }
- // Checks & Fixes
- if config.ProcessLimit < 1 {
- config.ProcessLimit = defConfig_ProcessLimit
- }
- if config.DiscordTimeout < 10 {
- config.DiscordTimeout = defConfig_DiscordTimeout
- }
- if config.DownloadTimeout < 10 {
- config.DownloadTimeout = defConfig_DownloadTimeout
- }
- if config.DownloadRetryMax < 1 {
- config.DownloadRetryMax = defConfig_DownloadRetryMax
- }
- if config.CheckupRate < 1 {
- config.CheckupRate = defConfig_CheckupRate
- }
- if config.ConnectionCheckRate < 1 {
- config.ConnectionCheckRate = defConfig_ConnectionCheckRate
- }
- if config.PresenceRefreshRate < 1 {
- config.PresenceRefreshRate = defConfig_PresenceRefreshRate
- }
- if config.FilenameDateFormat == "" {
- config.FilenameDateFormat = defConfig_FilenameDateFormat
- }
- if config.FilenameFormat == "" {
- config.FilenameFormat = defConfig_FilenameFormat
- }
- if config.HistoryMaxJobs < 1 {
- config.HistoryMaxJobs = defConfig_HistoryMaxJobs
- }
- // Settings Output
- if config.SettingsOutput {
- dupeConfig := config
- if dupeConfig.Credentials.Token != "" && dupeConfig.Credentials.Token != placeholderToken {
- dupeConfig.Credentials.Token = "STRIPPED_FOR_OUTPUT"
- }
- if dupeConfig.Credentials.Email != "" && dupeConfig.Credentials.Email != placeholderEmail {
- dupeConfig.Credentials.Email = "STRIPPED_FOR_OUTPUT"
- }
- if dupeConfig.Credentials.Password != "" && dupeConfig.Credentials.Password != placeholderPassword {
- dupeConfig.Credentials.Password = "STRIPPED_FOR_OUTPUT"
- }
- if dupeConfig.Credentials.TwitterUsername != "" {
- dupeConfig.Credentials.TwitterUsername = "STRIPPED_FOR_OUTPUT"
- }
- if dupeConfig.Credentials.TwitterPassword != "" {
- dupeConfig.Credentials.TwitterPassword = "STRIPPED_FOR_OUTPUT"
- }
- if dupeConfig.Credentials.InstagramUsername != "" {
- dupeConfig.Credentials.InstagramUsername = "STRIPPED_FOR_OUTPUT"
- }
- if dupeConfig.Credentials.InstagramPassword != "" {
- dupeConfig.Credentials.InstagramPassword = "STRIPPED_FOR_OUTPUT"
- }
- if dupeConfig.Credentials.FlickrApiKey != "" {
- dupeConfig.Credentials.FlickrApiKey = "STRIPPED_FOR_OUTPUT"
- }
- s, err := json.MarshalIndent(dupeConfig, "", "\t")
- if err != nil {
- log.Println(lg("Debug", "loadConfig", color.HiRedString, "Failed to output...\t%s", err))
- } else {
- log.Println(lg("Debug", "loadConfig", color.HiYellowString, "Parsed into JSON:\n\n%s", color.YellowString(string(s))))
- }
- }
- // Credentials Check
- if (config.Credentials.Token == "" || config.Credentials.Token == placeholderToken) &&
- (config.Credentials.Email == "" || config.Credentials.Email == placeholderEmail) &&
- (config.Credentials.Password == "" || config.Credentials.Password == placeholderPassword) {
- log.Println(lg("Settings", "loadConfig", color.HiRedString, "No valid discord login found..."))
- log.Println(lg("Settings", "loadConfig", color.HiYellowString, "Please save your credentials & info into \"%s\" then restart...", configFile))
- log.Println(lg("Settings", "loadConfig", color.MagentaString, "If your credentials are already properly saved, please ensure you're following proper JSON format syntax..."))
- log.Println(lg("Settings", "loadConfig", color.MagentaString, "You DO NOT NEED token *AND* email/password, just one OR the other."))
- properExit()
- }
- allString := ""
- if config.All != nil {
- allString = ", ALL ENABLED"
- }
- log.Println(lg("Settings", "", color.HiYellowString,
- "Loaded - bound to %d channel%s, %d categories, %d server%s, %d user%s%s",
- getBoundChannelsCount(), pluralS(getBoundChannelsCount()),
- getBoundCategoriesCount(),
- getBoundServersCount(), pluralS(getBoundServersCount()),
- getBoundUsersCount(), pluralS(getBoundUsersCount()), allString,
- ))
- // SETTINGS TO BE APPLIED IMMEDIATELY
- if config.ProcessLimit > 0 {
- runtime.GOMAXPROCS(config.ProcessLimit)
- }
- }
- return nil
- }
- func createConfig() {
- log.Println(lg("Settings", "create", color.YellowString, "Creating new settings file..."))
- enteredBaseChannel := "REPLACE_WITH_DISCORD_CHANNEL_ID_TO_DOWNLOAD_FROM"
- enteredBaseDestination := "REPLACE_WITH_FOLDER_LOCATION_TO_DOWNLOAD_TO"
- // Separate from Defaultconfiguration because there's some elements we want to strip for settings creation
- defaultConfig := configuration{
- Credentials: configurationCredentials{
- Token: placeholderToken,
- Email: placeholderEmail,
- Password: placeholderPassword,
- },
- Admins: []string{"REPLACE_WITH_YOUR_DISCORD_USER_ID"},
- CommandPrefix: defConfig_CommandPrefix,
- ScanOwnMessages: defConfig_ScanOwnMessages,
- PresenceEnabled: defConfig_PresenceEnabled,
- PresenceStatus: defConfig_PresenceStatus,
- PresenceType: defConfig_PresenceType,
- ReactWhenDownloaded: defConfig_ReactWhenDownloaded,
- GithubUpdateChecking: defConfig_GithubUpdateChecking,
- Debug: defConfig_Debug,
- }
- // Import old config
- if _, err := os.Stat("config.ini"); err == nil {
- log.Println(lg("Settings", "create", color.HiGreenString,
- "Detected config.ini from Seklfreak's discord-image-downloader-go, importing..."))
- cfg, err := ini.Load("config.ini")
- if err != nil {
- log.Println(lg("Settings", "create", color.HiRedString,
- "Unable to read your old config file:\t%s", err))
- cfg = ini.Empty()
- } else { // Import old ini
- importKey := func(section string, key string, outVar interface{}, outType string) bool {
- if cfg.Section(section).HasKey(key) {
- if outType == "string" {
- outVar = cfg.Section(section).Key(key).String()
- } else if outType == "int" {
- outVar = cfg.Section(section).Key(key).MustInt()
- } else if outType == "bool" {
- outVar = cfg.Section(section).Key(key).MustBool()
- }
- log.Println(lg("Settings", "create", color.GreenString, "IMPORTED %s - %s:\t\t\t%s", section, key, outVar))
- return true
- }
- return false
- }
- // Auth
- if !importKey("auth", "token", &defaultConfig.Credentials.Token, "string") {
- defaultConfig.Credentials.Token = ""
- }
- if !importKey("auth", "email", &defaultConfig.Credentials.Email, "string") {
- defaultConfig.Credentials.Email = ""
- }
- if !importKey("auth", "password", &defaultConfig.Credentials.Password, "string") {
- defaultConfig.Credentials.Password = ""
- }
- importKey("flickr", "api key", &defaultConfig.Credentials.FlickrApiKey, "string")
- // General
- importKey("general", "max download retries", &defaultConfig.DownloadRetryMax, "int")
- importKey("general", "download timeout", &defaultConfig.DownloadTimeout, "int")
- // Status
- importKey("status", "status enabled", &defaultConfig.PresenceEnabled, "bool")
- importKey("status", "status type", &defaultConfig.PresenceStatus, "string")
- importKey("status", "status label", &defaultConfig.PresenceType, "int")
- // Channels
- InteractiveChannelWhitelist := cfg.Section("interactive channels").KeysHash()
- for key := range InteractiveChannelWhitelist {
- newChannel := configurationAdminChannel{
- ChannelID: key,
- }
- log.Println(lg("Settings", "create", color.GreenString, "IMPORTED Admin Channel:\t\t%s", key))
- defaultConfig.AdminChannels = append(defaultConfig.AdminChannels, newChannel)
- }
- ChannelWhitelist := cfg.Section("channels").KeysHash()
- for key, value := range ChannelWhitelist {
- newChannel := configurationSource{
- ChannelID: key,
- Destination: value,
- }
- log.Println(lg("Settings", "create", color.GreenString, "IMPORTED Channel:\t\t\t%s to \"%s\"", key, value))
- defaultConfig.Channels = append(defaultConfig.Channels, newChannel)
- }
- }
- log.Println(lg("Settings", "create", color.HiGreenString,
- "Finished importing config.ini from Seklfreak's discord-image-downloader-go!"))
- } else {
- baseChannel := configurationSource{
- ChannelID: enteredBaseChannel,
- Destination: enteredBaseDestination,
- Enabled: &defSource_Enabled,
- Save: &config.Save,
- AllowCommands: &config.AllowCommands,
- SendErrorMessages: &config.SendErrorMessages,
- ScanEdits: &config.ScanEdits,
- IgnoreBots: &config.IgnoreBots,
- PresenceEnabled: &config.PresenceEnabled,
- ReactWhenDownloadedHistory: &config.ReactWhenDownloadedHistory,
- DivideByType: &config.DivideByType,
- SaveImages: &config.SaveImages,
- SaveVideos: &config.SaveVideos,
- }
- defaultConfig.Channels = append(defaultConfig.Channels, baseChannel)
- baseAdminChannel := configurationAdminChannel{
- ChannelID: "REPLACE_WITH_DISCORD_CHANNEL_ID_FOR_ADMIN_COMMANDS",
- }
- defaultConfig.AdminChannels = append(defaultConfig.AdminChannels, baseAdminChannel)
- //TODO: Improve, this is very crude, I just wanted *something* for this.
- log.Print(lg("Settings", "create", color.HiCyanString, "Would you like to enter settings info now? [Y/N]: "))
- reader := bufio.NewReader(os.Stdin)
- inputCredsYN, _ := reader.ReadString('\n')
- inputCredsYN = strings.ReplaceAll(inputCredsYN, "\n", "")
- inputCredsYN = strings.ReplaceAll(inputCredsYN, "\r", "")
- if strings.Contains(strings.ToLower(inputCredsYN), "y") {
- EnterCreds:
- log.Print(color.HiCyanString("Token or Login? [\"token\"/\"login\"]: "))
- inputCreds, _ := reader.ReadString('\n')
- inputCreds = strings.ReplaceAll(inputCreds, "\n", "")
- inputCreds = strings.ReplaceAll(inputCreds, "\r", "")
- if strings.Contains(strings.ToLower(inputCreds), "token") {
- EnterToken:
- log.Print(color.HiCyanString("Enter token: "))
- inputToken, _ := reader.ReadString('\n')
- inputToken = strings.ReplaceAll(inputToken, "\n", "")
- inputToken = strings.ReplaceAll(inputToken, "\r", "")
- if inputToken != "" {
- defaultConfig.Credentials.Token = inputToken
- } else {
- log.Println(lg("Settings", "create", color.HiRedString, "Please input token..."))
- goto EnterToken
- }
- } else if strings.Contains(strings.ToLower(inputCreds), "login") {
- EnterEmail:
- log.Print(color.HiCyanString("Enter email: "))
- inputEmail, _ := reader.ReadString('\n')
- inputEmail = strings.ReplaceAll(inputEmail, "\n", "")
- inputEmail = strings.ReplaceAll(inputEmail, "\r", "")
- if strings.Contains(inputEmail, "@") {
- defaultConfig.Credentials.Email = inputEmail
- EnterPassword:
- log.Print(color.HiCyanString("Enter password: "))
- inputPassword, _ := reader.ReadString('\n')
- inputPassword = strings.ReplaceAll(inputPassword, "\n", "")
- inputPassword = strings.ReplaceAll(inputPassword, "\r", "")
- if inputPassword != "" {
- defaultConfig.Credentials.Password = inputPassword
- } else {
- log.Println(lg("Settings", "create", color.HiRedString, "Please input password..."))
- goto EnterPassword
- }
- } else {
- log.Println(lg("Settings", "create", color.HiRedString, "Please input email..."))
- goto EnterEmail
- }
- } else {
- log.Println(lg("Settings", "create", color.HiRedString, "Please input \"token\" or \"login\"..."))
- goto EnterCreds
- }
- EnterAdmin:
- log.Print(color.HiCyanString("Input your Discord User ID: "))
- inputAdmin, _ := reader.ReadString('\n')
- inputAdmin = strings.ReplaceAll(inputAdmin, "\n", "")
- inputAdmin = strings.ReplaceAll(inputAdmin, "\r", "")
- if isNumeric(inputAdmin) {
- defaultConfig.Admins = []string{inputAdmin}
- } else {
- log.Println(lg("Settings", "create", color.HiRedString, "Please input your Discord User ID..."))
- goto EnterAdmin
- }
- //TODO: Base channel setup? Would be kind of annoying and may limit options
- //TODO: Admin channel setup?
- }
- }
- log.Println(lg("Settings", "create", color.MagentaString,
- "The default settings will be missing some options to avoid clutter."))
- log.Println(lg("Settings", "create", color.HiMagentaString,
- "There are MANY MORE SETTINGS! If you would like to maximize customization, see the GitHub README for all available settings."))
- defaultJSON, err := json.MarshalIndent(defaultConfig, "", "\t")
- if err != nil {
- log.Println(lg("Settings", "create", color.HiRedString, "Failed to format new settings...\t%s", err))
- } else {
- err := os.WriteFile(configFile, defaultJSON, 0644)
- if err != nil {
- log.Println(lg("Settings", "create", color.HiRedString, "Failed to save new settings file...\t%s", err))
- } else {
- log.Println(lg("Settings", "create", color.HiYellowString, "Created new settings file..."))
- log.Println(lg("Settings", "create", color.HiYellowString,
- "Please save your credentials & info into \"%s\" then restart...", configFile))
- log.Println(lg("Settings", "create", color.MagentaString,
- "You DO NOT NEED token *AND* email/password, just one OR the other."))
- log.Println(lg("Settings", "create", color.MagentaString,
- "THERE ARE MANY HIDDEN SETTINGS AVAILABLE, SEE THE GITHUB README github.com/"+projectRepoBase))
- }
- }
- }
- func sourceDefault(channel *configurationSource) {
- // These have to use the default variables since literal values and consts can't be set to the pointers
- // Setup
- if channel.Enabled == nil {
- channel.Enabled = &defSource_Enabled
- }
- if channel.Save == nil {
- channel.Save = &config.Save
- }
- if channel.AllowCommands == nil {
- channel.AllowCommands = &config.AllowCommands
- }
- if channel.SendErrorMessages == nil {
- channel.SendErrorMessages = &config.SendErrorMessages
- }
- if channel.ScanEdits == nil {
- channel.ScanEdits = &config.ScanEdits
- }
- if channel.IgnoreBots == nil {
- channel.IgnoreBots = &config.IgnoreBots
- }
- if channel.SendErrorMessages == nil {
- channel.SendErrorMessages = &config.SendErrorMessages
- }
- if channel.SendFileToChannel == nil && config.SendFileToChannel != "" {
- channel.SendFileToChannel = &config.SendFileToChannel
- }
- if channel.SendFileToChannels == nil && config.SendFileToChannels != nil {
- channel.SendFileToChannels = &config.SendFileToChannels
- }
- if channel.SendFileDirectly == nil {
- channel.SendFileDirectly = &config.SendFileDirectly
- }
- if channel.SendFileCaption == nil && config.SendFileCaption != "" {
- channel.SendFileCaption = &config.SendFileCaption
- }
- if channel.FilenameDateFormat == nil {
- channel.FilenameDateFormat = &config.FilenameDateFormat
- }
- if channel.FilenameFormat == nil {
- channel.FilenameFormat = &config.FilenameFormat
- }
- // Appearance
- if channel.PresenceEnabled == nil {
- channel.PresenceEnabled = &config.PresenceEnabled
- }
- if channel.ReactWhenDownloaded == nil {
- channel.ReactWhenDownloaded = &config.ReactWhenDownloaded
- }
- if channel.ReactWhenDownloadedEmoji == nil && config.ReactWhenDownloadedEmoji != nil {
- channel.ReactWhenDownloadedEmoji = config.ReactWhenDownloadedEmoji
- }
- if channel.ReactWhenDownloadedHistory == nil {
- channel.ReactWhenDownloadedHistory = &config.ReactWhenDownloadedHistory
- }
- if channel.BlacklistReactEmojis == nil {
- channel.BlacklistReactEmojis = &[]string{}
- }
- if channel.HistoryTyping == nil {
- channel.HistoryTyping = &config.HistoryTyping
- }
- if channel.EmbedColor == nil && config.EmbedColor != nil {
- channel.EmbedColor = config.EmbedColor
- }
- // History
- if channel.AutoHistory == nil {
- channel.AutoHistory = &config.AutoHistory
- }
- if channel.AutoHistoryBefore == nil {
- channel.AutoHistoryBefore = &config.AutoHistoryBefore
- }
- if channel.AutoHistorySince == nil {
- channel.AutoHistorySince = &config.AutoHistorySince
- }
- if channel.SendAutoHistoryStatus == nil {
- channel.SendAutoHistoryStatus = &config.SendAutoHistoryStatus
- }
- if channel.SendHistoryStatus == nil {
- channel.SendHistoryStatus = &config.SendHistoryStatus
- }
- // Rules for Saving
- if channel.DivideByYear == nil {
- channel.DivideByYear = &config.DivideByYear
- }
- if channel.DivideByMonth == nil {
- channel.DivideByMonth = &config.DivideByMonth
- }
- if channel.DivideByServer == nil {
- channel.DivideByServer = &config.DivideByServer
- }
- if channel.DivideByChannel == nil {
- channel.DivideByChannel = &config.DivideByChannel
- }
- if channel.DivideByUser == nil {
- channel.DivideByUser = &config.DivideByUser
- }
- if channel.DivideByType == nil {
- channel.DivideByType = &config.DivideByType
- }
- if channel.DivideFoldersUseID == nil {
- channel.DivideFoldersUseID = &config.DivideFoldersUseID
- }
- if channel.SaveImages == nil {
- channel.SaveImages = &config.SaveImages
- }
- if channel.SaveVideos == nil {
- channel.SaveVideos = &config.SaveVideos
- }
- if channel.SaveAudioFiles == nil {
- channel.SaveAudioFiles = &config.SaveAudioFiles
- }
- if channel.SaveTextFiles == nil {
- channel.SaveTextFiles = &config.SaveTextFiles
- }
- if channel.SaveOtherFiles == nil {
- channel.SaveOtherFiles = &config.SaveOtherFiles
- }
- if channel.SavePossibleDuplicates == nil {
- channel.SavePossibleDuplicates = &config.SavePossibleDuplicates
- }
- if channel.Filters == nil {
- channel.Filters = &configurationSourceFilters{}
- }
- if channel.Filters.BlockedExtensions == nil && config.Filters.BlockedExtensions != nil {
- channel.Filters.BlockedExtensions = config.Filters.BlockedExtensions
- }
- if channel.Filters.BlockedPhrases == nil && config.Filters.BlockedPhrases != nil {
- channel.Filters.BlockedPhrases = config.Filters.BlockedPhrases
- }
- if channel.Duplo == nil {
- channel.Duplo = &config.Duplo
- }
- if channel.DuploThreshold == nil {
- channel.DuploThreshold = &config.DuploThreshold
- }
- // Misc Rules
- if channel.LogLinks == nil {
- channel.LogLinks = &configurationSourceLog{}
- }
- if channel.LogLinks.DestinationIsFolder == nil {
- channel.LogLinks.DestinationIsFolder = &defSourceLog_DestinationIsFolder
- }
- if channel.LogLinks.DivideLogsByServer == nil {
- channel.LogLinks.DivideLogsByServer = &defSourceLog_DivideLogsByServer
- }
- if channel.LogLinks.DivideLogsByChannel == nil {
- channel.LogLinks.DivideLogsByChannel = &defSourceLog_DivideLogsByChannel
- }
- if channel.LogLinks.DivideLogsByUser == nil {
- channel.LogLinks.DivideLogsByUser = &defSourceLog_DivideLogsByUser
- }
- if channel.LogLinks.DivideLogsByStatus == nil {
- channel.LogLinks.DivideLogsByStatus = &defSourceLog_DivideLogsByStatus
- }
- if channel.LogLinks.LogDownloads == nil {
- channel.LogLinks.LogDownloads = &defSourceLog_LogDownloads
- }
- if channel.LogLinks.LogFailures == nil {
- channel.LogLinks.LogFailures = &defSourceLog_LogFailures
- }
- if channel.LogMessages == nil {
- channel.LogMessages = &configurationSourceLog{}
- }
- if channel.LogMessages.DestinationIsFolder == nil {
- channel.LogMessages.DestinationIsFolder = &defSourceLog_DestinationIsFolder
- }
- if channel.LogMessages.DivideLogsByServer == nil {
- channel.LogMessages.DivideLogsByServer = &defSourceLog_DivideLogsByServer
- }
- if channel.LogMessages.DivideLogsByChannel == nil {
- channel.LogMessages.DivideLogsByChannel = &defSourceLog_DivideLogsByChannel
- }
- if channel.LogMessages.DivideLogsByUser == nil {
- channel.LogMessages.DivideLogsByUser = &defSourceLog_DivideLogsByUser
- }
- // LAZY CHECKS
- if channel.Duplo != nil {
- if *channel.Duplo {
- sourceHasDuplo = true
- }
- }
- }
- var sourceHasDuplo bool = false
- func adminChannelDefault(channel *configurationAdminChannel) {
- if channel.LogProgram == nil {
- channel.LogProgram = &adefConfig_LogProgram
- }
- if channel.LogStatus == nil {
- channel.LogStatus = &adefConfig_LogStatus
- }
- if channel.LogErrors == nil {
- channel.LogErrors = &adefConfig_LogErrors
- }
- if channel.UnlockCommands == nil {
- channel.UnlockCommands = &adefConfig_UnlockCommands
- }
- }
- //#endregion
- //#region Functions, Admin & Source
- func isNestedMessage(subjectMessage *discordgo.Message, targetChannel string) bool {
- if subjectMessage.ID != "" {
- _, err := bot.State.Message(targetChannel, subjectMessage.ChannelID)
- return err == nil
- }
- return false
- }
- var emptyConfig configurationSource = configurationSource{}
- func getSource(m *discordgo.Message, c *discordgo.Channel) configurationSource {
- subjectID := m.ChannelID
- if c != nil {
- if c.ParentID != "" {
- subjectID = c.ParentID
- }
- }
- // Channel
- for _, item := range config.Channels {
- // Single Channel Config
- if subjectID == item.ChannelID || isNestedMessage(m, item.ChannelID) {
- return item
- }
- // Multi-Channel Config
- if item.ChannelIDs != nil {
- for _, subchannel := range *item.ChannelIDs {
- if subjectID == subchannel || isNestedMessage(m, subchannel) {
- return item
- }
- }
- }
- }
- // Category Config
- for _, item := range config.Categories {
- if item.CategoryID != "" {
- channel, err := bot.State.Channel(subjectID)
- if err == nil {
- if channel.ParentID == item.CategoryID {
- return item
- }
- }
- }
- // Multi-Category Config
- if item.CategoryIDs != nil {
- for _, subcategory := range *item.CategoryIDs {
- channel, err := bot.State.Channel(subjectID)
- if err == nil {
- if channel.ParentID == subcategory {
- if item.CategoryBlacklist != nil {
- if stringInSlice(channel.ParentID, *item.CategoryBlacklist) {
- return emptyConfig
- }
- }
- return item
- }
- }
- }
- }
- }
- // Server
- for _, item := range config.Servers {
- if item.ServerID != "" {
- guild, err := bot.State.Guild(item.ServerID)
- if err == nil {
- for _, channel := range guild.Channels {
- if subjectID == channel.ID || isNestedMessage(m, channel.ID) {
- // Channel Blacklisting within Server
- if item.ServerBlacklist != nil {
- if stringInSlice(subjectID, *item.ServerBlacklist) {
- return emptyConfig
- }
- // Categories
- if channel.ParentID != "" {
- if stringInSlice(channel.ParentID, *item.ServerBlacklist) {
- return emptyConfig
- }
- }
- }
- return item
- }
- }
- }
- }
- // Multi-Server Config
- if item.ServerIDs != nil {
- for _, subserver := range *item.ServerIDs {
- guild, err := bot.State.Guild(subserver)
- if err == nil {
- for _, channel := range guild.Channels {
- if subjectID == channel.ID || isNestedMessage(m, channel.ID) {
- // Channel Blacklisting within Servers
- if item.ServerBlacklist != nil {
- if stringInSlice(subjectID, *item.ServerBlacklist) {
- return emptyConfig
- }
- // Categories
- if channel.ParentID != "" {
- if stringInSlice(channel.ParentID, *item.ServerBlacklist) {
- return emptyConfig
- }
- }
- }
- return item
- }
- }
- }
- }
- }
- }
- // User Config
- for _, item := range config.Users {
- if item.UserID != "" {
- if m.Author.ID == item.UserID {
- return item
- }
- }
- // Multi-User Config
- if item.UserIDs != nil {
- for _, subuser := range *item.UserIDs {
- if m.Author.ID == subuser {
- return item
- }
- }
- }
- }
- // All
- if config.All != nil {
- if config.AllBlacklistChannels != nil {
- if stringInSlice(subjectID, *config.AllBlacklistChannels) {
- return emptyConfig
- }
- }
- if config.AllBlacklistCategories != nil {
- chinf, err := bot.State.Channel(subjectID)
- if err == nil {
- if stringInSlice(chinf.ParentID, *config.AllBlacklistCategories) || stringInSlice(subjectID, *config.AllBlacklistCategories) {
- return emptyConfig
- }
- }
- }
- if config.AllBlacklistServers != nil {
- if stringInSlice(m.GuildID, *config.AllBlacklistServers) {
- return emptyConfig
- }
- }
- if config.AllBlacklistUsers != nil && m.Author != nil {
- if stringInSlice(m.Author.ID, *config.AllBlacklistUsers) {
- return emptyConfig
- }
- }
- return *config.All
- }
- return emptyConfig
- }
- func isAdminChannelRegistered(ChannelID string) bool {
- if config.AdminChannels != nil {
- for _, item := range config.AdminChannels {
- // Single Channel Config
- if ChannelID == item.ChannelID {
- return true
- }
- // Multi-Channel Config
- if item.ChannelIDs != nil {
- if stringInSlice(ChannelID, *item.ChannelIDs) {
- return true
- }
- }
- }
- }
- return false
- }
- func getAdminChannelConfig(ChannelID string) configurationAdminChannel {
- if config.AdminChannels != nil {
- for _, item := range config.AdminChannels {
- // Single Channel Config
- if ChannelID == item.ChannelID {
- return item
- }
- // Multi-Channel Config
- if item.ChannelIDs != nil {
- for _, subchannel := range *item.ChannelIDs {
- if ChannelID == subchannel {
- return item
- }
- }
- }
- }
- }
- return configurationAdminChannel{}
- }
- func isCommandableChannel(m *discordgo.Message) bool {
- if config.AllowGeneralCommands {
- return true
- }
- if isAdminChannelRegistered(m.ChannelID) {
- return true
- } else if channelConfig := getSource(m, nil); channelConfig != emptyConfig {
- if *channelConfig.AllowCommands || isBotAdmin(m) || m.Author.ID == bot.State.User.ID {
- return true
- }
- }
- return false
- }
- func getBoundUsers() []string {
- var users []string
- for _, item := range config.Users {
- if item.UserID != "" {
- if !stringInSlice(item.UserID, users) {
- users = append(users, item.UserID)
- }
- } else if item.UserIDs != nil {
- for _, subuser := range *item.UserIDs {
- if subuser != "" {
- if !stringInSlice(subuser, users) {
- users = append(users, subuser)
- }
- }
- }
- }
- }
- return users
- }
- func getBoundUsersCount() int {
- return len(getBoundUsers())
- }
- func getBoundServers() []string {
- var servers []string
- for _, item := range config.Servers {
- if item.ServerID != "" {
- if !stringInSlice(item.ServerID, servers) {
- servers = append(servers, item.ServerID)
- }
- } else if item.ServerIDs != nil {
- for _, subserver := range *item.ServerIDs {
- if subserver != "" {
- if !stringInSlice(subserver, servers) {
- servers = append(servers, subserver)
- }
- }
- }
- }
- }
- return servers
- }
- func getBoundServersCount() int {
- return len(getBoundServers())
- }
- func getBoundChannels() []string {
- var channels []string
- for _, item := range config.Channels {
- if item.ChannelID != "" {
- if !stringInSlice(item.ChannelID, channels) {
- channels = append(channels, item.ChannelID)
- }
- } else if item.ChannelIDs != nil {
- for _, subchannel := range *item.ChannelIDs {
- if subchannel != "" {
- if !stringInSlice(subchannel, channels) {
- channels = append(channels, subchannel)
- }
- }
- }
- }
- }
- return channels
- }
- func getBoundChannelsCount() int {
- return len(getBoundChannels())
- }
- func getBoundCategories() []string {
- var categories []string
- for _, item := range config.Categories {
- if item.CategoryID != "" {
- if !stringInSlice(item.CategoryID, categories) {
- categories = append(categories, item.CategoryID)
- }
- } else if item.CategoryIDs != nil {
- for _, subcategory := range *item.CategoryIDs {
- if subcategory != "" {
- if !stringInSlice(subcategory, categories) {
- categories = append(categories, subcategory)
- }
- }
- }
- }
- }
- return categories
- }
- func getBoundCategoriesCount() int {
- return len(getBoundCategories())
- }
- func getAllRegisteredChannels() []string {
- var channels []string
- if config.All != nil { // ALL MODE
- for _, guild := range bot.State.Guilds {
- if config.AllBlacklistServers != nil {
- if stringInSlice(guild.ID, *config.AllBlacklistServers) {
- continue
- }
- }
- for _, channel := range guild.Channels {
- if r := getSource(&discordgo.Message{ChannelID: channel.ID}, nil); r == emptyConfig { // easier than redoing it all but way less efficient, im lazy
- continue
- } else {
- if hasPerms(channel.ID, discordgo.PermissionViewChannel) && hasPerms(channel.ID, discordgo.PermissionReadMessageHistory) {
- channels = append(channels, channel.ID)
- }
- }
- }
- }
- } else { // STANDARD MODE
- // Compile all channels sourced from config servers
- for _, server := range config.Servers {
- if server.ServerIDs != nil {
- for _, subserver := range *server.ServerIDs {
- guild, err := bot.State.Guild(subserver)
- if err == nil {
- for _, channel := range guild.Channels {
- if hasPerms(channel.ID, discordgo.PermissionReadMessageHistory) {
- channels = append(channels, channel.ID)
- }
- }
- }
- }
- } else if isNumeric(server.ServerID) {
- guild, err := bot.State.Guild(server.ServerID)
- if err == nil {
- for _, channel := range guild.Channels {
- if hasPerms(channel.ID, discordgo.PermissionReadMessageHistory) {
- channels = append(channels, channel.ID)
- }
- }
- }
- }
- }
- // Compile all config channels under categories, no practical way to poll these other than checking state.
- for _, guild := range bot.State.Guilds {
- for _, channel := range guild.Channels {
- for _, source := range config.Categories {
- if source.CategoryIDs != nil {
- for _, category := range *source.CategoryIDs {
- if channel.ParentID == category {
- channels = append(channels, channel.ID)
- }
- }
- } else if isNumeric(source.CategoryID) {
- if channel.ParentID == source.CategoryID {
- channels = append(channels, channel.ID)
- }
- }
- }
- }
- }
- // Compile all config channels
- for _, channel := range config.Channels {
- if channel.ChannelIDs != nil {
- channels = append(channels, *channel.ChannelIDs...)
- } else if isNumeric(channel.ChannelID) {
- channels = append(channels, channel.ChannelID)
- }
- }
- }
- return channels
- }
- //#endregion
|