// here, support a function that maps a given redis key to a dynamodb table key and value field func NewDynamoModule(keymap KeyMapper) *DynamoModule { module := &DynamoModule{} cfgdir := "/etc" cfg := &module.config ok := logging.ReadModuleConfig(cfg, cfgdir, "dynamo") || logging.ReadModuleConfig(cfg, ".", "dynamo") sess := session.New(&aws.Config{Region: aws.String("ap-southeast-1")}) if !ok { log.Println("failed to read dynamo config, using defaults") } else { sess = session.New(&aws.Config{ Region: aws.String(cfg.Server.Region), Endpoint: aws.String(cfg.Server.Endpoint), DisableSSL: aws.Bool(cfg.Server.DisableSSL), }) } module.client = dynamodb.New(sess) if keymap != nil { module.keyMapper = keymap } else { module.keyMapper = module.defaultMapper } if cfg.Server.CacheDuration > 0 { logging.Debug.Println("activiating cache, TTL", cfg.Server.CacheDuration) module.cache = cache.NewMemoryWithTTL(time.Duration(cfg.Server.CacheDuration) * time.Second) } return module }
// New creates a new Kloud instance without initializing the default providers. func New() *Kloud { log := logging.NewLogger(NAME) kld := &Kloud{ idlock: idlock.New(), Log: log, Eventers: make(map[string]eventer.Eventer), providers: make(map[string]Provider), statusCache: cache.NewMemoryWithTTL(time.Second * 10), } kld.statusCache.StartGC(time.Second * 5) return kld }
func (k *Kite) verifyInit() { k.configMu.Lock() defer k.configMu.Unlock() k.verifyFunc = k.Config.VerifyFunc if k.verifyFunc == nil { k.verifyFunc = k.selfVerify } k.verifyAudienceFunc = k.Config.VerifyAudienceFunc if k.verifyAudienceFunc == nil { k.verifyAudienceFunc = k.verifyAudience } ttl := k.Config.VerifyTTL if ttl == 0 { ttl = 5 * time.Minute } if ttl > 0 { k.mu.Lock() k.verifyCache = cache.NewMemoryWithTTL(ttl) k.mu.Unlock() k.verifyCache.StartGC(ttl / 2) } key, err := jwt.ParseRSAPublicKeyFromPEM([]byte(k.Config.KontrolKey)) if err != nil { k.Log.Error("unable to init kontrol key: %s", err) return } k.kontrolKey = key }
// ---------------------------------------------------------------------------- func main() { commands, appConfig, err := getConfig() if err != nil { log.Fatal(err) } bot, err := tgbotapi.NewBotAPI(appConfig.token) if err != nil { log.Fatal(err) } log.Printf("Authorized on bot account: @%s", bot.Self.UserName) tgbotConfig := tgbotapi.NewUpdate(0) tgbotConfig.Timeout = appConfig.botTimeout botUpdatesChan, err := bot.GetUpdatesChan(tgbotConfig) if err != nil { log.Fatal(err) } users := NewUsers(appConfig) messageSignal := make(chan BotMessage, MessagesQueueSize) vacuumTicker := time.Tick(SecondsForOldUsersBeforeVacuum * time.Second) saveToBDTicker := make(<-chan time.Time) exitSignal := make(chan struct{}) systemExitSignal := make(chan os.Signal) signal.Notify(systemExitSignal, os.Interrupt, os.Kill) if appConfig.persistentUsers { saveToBDTicker = time.Tick(SecondsForAutoSaveUsersToDB * time.Second) } var cacheTTL *cache.MemoryTTL if appConfig.cache > 0 { cacheTTL = cache.NewMemoryWithTTL(time.Duration(appConfig.cache) * time.Second) cacheTTL.StartGC(time.Duration(appConfig.cache) * time.Second * 2) } // all /shell2telegram sub-commands handlers internalCommands := map[string]func(Ctx) string{ "stat": cmdShell2telegramStat, "ban": cmdShell2telegramBan, "search": cmdShell2telegramSearch, "desc": cmdShell2telegramDesc, "rm": cmdShell2telegramRm, "exit": cmdShell2telegramExit, "version": cmdShell2telegramVersion, "broadcast_to_root": cmdShell2telegramBroadcastToRoot, "message_to_user": cmdShell2telegramMessageToUser, } doExit := false for !doExit { select { case telegramUpdate := <-botUpdatesChan: var messageCmd, messageArgs string allUserMessage := telegramUpdate.Message.Text if len(allUserMessage) > 0 && allUserMessage[0] == '/' { messageCmd, messageArgs = splitStringHalfBySpace(allUserMessage) } else { messageCmd, messageArgs = "/:plain_text", allUserMessage } allowPlainText := false if _, ok := commands["/:plain_text"]; ok { allowPlainText = true } replayMsg := "" if len(messageCmd) > 0 && (messageCmd != "/:plain_text" || allowPlainText) { users.AddNew(telegramUpdate.Message) userID := telegramUpdate.Message.From.ID allowExec := appConfig.allowAll || users.IsAuthorized(userID) ctx := Ctx{ appConfig: &appConfig, users: &users, commands: commands, userID: userID, allowExec: allowExec, messageCmd: messageCmd, messageArgs: messageArgs, messageSignal: messageSignal, chatID: telegramUpdate.Message.Chat.ID, exitSignal: exitSignal, cacheTTL: cacheTTL, } switch { // commands ................................. case !appConfig.isPublicBot && (messageCmd == "/auth" || messageCmd == "/authroot"): replayMsg = cmdAuth(ctx) case messageCmd == "/help": replayMsg = cmdHelp(ctx) case messageCmd == "/shell2telegram" && users.IsRoot(userID): messageSubCmd := "" messageSubCmd, messageArgs = splitStringHalfBySpace(messageArgs) ctx.messageArgs = messageArgs if cmdHandler, ok := internalCommands[messageSubCmd]; ok { replayMsg = cmdHandler(ctx) } else { replayMsg = "Sub-command not found" } case allowExec && (allowPlainText && messageCmd == "/:plain_text" || messageCmd[0] == '/'): cmdUser(ctx) } // switch for commands if appConfig.logCommands { log.Printf("%s: %s", users.String(userID), allUserMessage) } sendMessage(messageSignal, telegramUpdate.Message.Chat.ID, []byte(replayMsg), false) } case botMessage := <-messageSignal: switch { case botMessage.messageType == msgIsText && !stringIsEmpty(botMessage.message): messageConfig := tgbotapi.NewMessage(botMessage.chatID, botMessage.message) if botMessage.isMarkdown { messageConfig.ParseMode = tgbotapi.ModeMarkdown } _, err = bot.Send(messageConfig) case botMessage.messageType == msgIsPhoto && len(botMessage.photo) > 0: bytesPhoto := tgbotapi.FileBytes{Name: botMessage.fileName, Bytes: botMessage.photo} _, err = bot.Send(tgbotapi.NewPhotoUpload(botMessage.chatID, bytesPhoto)) } if err != nil { log.Print("Bot send message error: ", err) } case <-saveToBDTicker: users.SaveToDB(appConfig.usersDB) case <-vacuumTicker: users.ClearOldUsers() case <-systemExitSignal: go func() { exitSignal <- struct{}{} }() case <-exitSignal: if appConfig.persistentUsers { users.needSaveDB = true users.SaveToDB(appConfig.usersDB) } doExit = true } } }
// NewTTL returns an in-memory cache with the specified // ttl expiration period. func NewTTL(t time.Duration) Cache { return cache.NewMemoryWithTTL(t) }
// Default creates an in-memory cache with the default // 24 hour expiration period. func Default() Cache { return cache.NewMemoryWithTTL(time.Hour * 24) }
func NewMemKeyPairStorageTTL(ttl time.Duration) *MemKeyPairStorage { return &MemKeyPairStorage{ id: cache.NewMemoryWithTTL(ttl), public: cache.NewMemoryWithTTL(ttl), } }
// Default creates an in-memory cache with the default // 30 minute expiration period. func Default() Cache { return cache.NewMemoryWithTTL(time.Minute * 30) }
// EndpointPresencePing provides ping endpoint EndpointPresencePing = "/presence/ping" EndpointPresenceListMembers = "/presence/listmembers" // EndpointPresencePingPrivate provides private ping endpoint EndpointPresencePingPrivate = "/private/presence/ping" ) const ( // EventName holds presence event name EventName = "presence_ping" ) var ( pingCache = cache.NewMemoryWithTTL(time.Hour) // this may lead to max 5 mins of invalid tracking data if a group changes // their sub status during that period groupCache = cache.NewMemoryWithTTL(time.Minute * 5) ) // Controller holds the basic context data for handlers type Controller struct { log logging.Logger conf *config.Config } // New creates a controller func New(log logging.Logger, conf *config.Config) *Controller { return &Controller{