Skip to content

Commit

Permalink
Refactoring - moved to standard context and linting changes
Browse files Browse the repository at this point in the history
  • Loading branch information
trakhimenok committed Apr 24, 2018
1 parent 33b4a35 commit 8ef5775
Show file tree
Hide file tree
Showing 45 changed files with 359 additions and 192 deletions.
38 changes: 38 additions & 0 deletions can-i-use-bots-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,44 @@ In case of `Yes` or `limited` there is a link to documentation where applicable.
<td align=center>?</td>
<td align=center>?</td>
</tr>
<tr>
<td colspan=6><b>Messages management</b></td>
</tr>
<tr>
<td>&nbsp;&nbsp;Edit message</td>
<td align=center>✅ limited</td>
<td align=center>?</td>
<td align=center>?</td>
<td align=center>?</td>
<td align=center>?</td>
</tr>
<tr>
<td>&nbsp;&nbsp;Delete message</td>
<td align=center>✅ limited</td>
<td align=center>?</td>
<td align=center>?</td>
<td align=center>?</td>
<td align=center>?</td>
</tr>
<tr>
<td colspan=6><b>Group chats</b></td>
</tr>
<tr>
<td>&nbsp;&nbsp;Can be added to group</td>
<td align=center>✅ Yes</td>
<td align=center>❌ no</td>
<td align=center>?</td>
<td align=center>?</td>
<td align=center>?</td>
</tr>
<tr>
<td>&nbsp;&nbsp;Group administration</td>
<td align=center>✅ Yes</td>
<td align=center>❌ no</td>
<td align=center>?</td>
<td align=center>?</td>
<td align=center>?</td>
</tr>
<tr>
<td colspan=6><b>Security</b></td>
</tr>
Expand Down
1 change: 1 addition & 0 deletions core/app_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bots

import "github.com/strongo/app"

// BotAppContext is a context for bot app
type BotAppContext interface {
strongo.AppContext
NewBotAppUserEntity() BotAppUser
Expand Down
10 changes: 6 additions & 4 deletions core/app_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ package bots

import (
"github.com/strongo/app"
"golang.org/x/net/context"
"context"
)

//type AppUserIntID int64

// BotAppUser holds information about bot app user
type BotAppUser interface {
strongo.AppUser
//GetAppUserIntID() int64
SetBotUserID(platform, botID, botUserId string)
SetBotUserID(platform, botID, botUserID string)
}

// BotAppUserStore interface for storing user information to persistent store
type BotAppUserStore interface {
GetAppUserByID(c context.Context, appUserId int64, appUser BotAppUser) error
CreateAppUser(c context.Context, botID string, actor WebhookActor) (appUserId int64, appUserEntity BotAppUser, err error)
GetAppUserByID(c context.Context, appUserID int64, appUser BotAppUser) error
CreateAppUser(c context.Context, botID string, actor WebhookActor) (appUserID int64, appUserEntity BotAppUser, err error)
//SaveAppUser(c context.Context, appUserId int64, appUserEntity BotAppUser) error
}
8 changes: 6 additions & 2 deletions core/bot_chat.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package bots

import (
"github.com/satori/go.uuid"
"golang.org/x/net/context"
"time"

"github.com/satori/go.uuid"
"context"
)

// BotChat provides data about bot chat
type BotChat interface {
GetBotID() string
SetBotID(botID string)
Expand Down Expand Up @@ -40,13 +42,15 @@ type BotChat interface {
GetGaClientID() uuid.UUID
}

// BotChatStore is interface for DAL to store bot chat data
type BotChatStore interface {
GetBotChatEntityByID(c context.Context, botID, botChatID string) (BotChat, error)
SaveBotChat(c context.Context, botID, botChatID string, chatEntity BotChat) error
NewBotChatEntity(c context.Context, botID string, botChat WebhookChat, appUserID int64, botUserID string, isAccessGranted bool) BotChat
Close(c context.Context) error // TODO: Was io.Closer, should it?
}

// NewChatID create a new bot chat ID, returns string
func NewChatID(botID, botChatID string) string {
return botID + ":" + botChatID
}
5 changes: 4 additions & 1 deletion core/bot_user.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package bots

import (
"golang.org/x/net/context"
"time"

"context"
)

// BotUser interface provides information about bot user
type BotUser interface {
GetAppUserIntID() int64
IsAccessGranted() bool
Expand All @@ -13,6 +15,7 @@ type BotUser interface {
SetDtUpdated(time time.Time)
}

// BotUserStore provider to store information about bot user
type BotUserStore interface {
GetBotUserById(c context.Context, botUserID interface{}) (BotUser, error)
SaveBotUser(c context.Context, botUserID interface{}, botUserEntity BotUser) error
Expand Down
26 changes: 20 additions & 6 deletions core/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,27 @@ package bots
import (
"fmt"
"net/url"
"strings"
)

// CommandAction defines an action bot can perform in response to a command
type CommandAction func(whc WebhookContext) (m MessageFromBot, err error)

// CallbackAction defines a callback action bot can perform in response to a callback command
type CallbackAction func(whc WebhookContext, callbackUrl *url.URL) (m MessageFromBot, err error)

// CommandMatcher returns true if action is matched to user input
type CommandMatcher func(Command, WebhookContext) bool

const DEFAULT_TITLE = ""
const SHORT_TITLE = "short_title"
// DefaultTitle key
const DefaultTitle = "" //

// ShortTitle key
const ShortTitle = "short_title"

//const LONG_TITLE = "long_title"
//const LongTitle = "long_title"

// Command defines command metadata and action
type Command struct {
InputTypes []WebhookInputType // Instant match if != WebhookInputUnknown && == whc.InputTypes()
Icon string
Expand All @@ -29,6 +38,7 @@ type Command struct {
CallbackAction CallbackAction
}

// NewCallbackCommand create a definition of a callback command
func NewCallbackCommand(code string, action CallbackAction) Command {
return Command{
Code: code,
Expand All @@ -41,13 +51,15 @@ func (c Command) String() string {
return fmt.Sprintf("Command{Code: '%v', InputTypes: %v, Icon: '%v', Title: '%v', ExactMatch: '%v', len(Command): %v, len(Replies): %v}", c.Code, c.InputTypes, c.Icon, c.Title, c.ExactMatch, len(c.Commands), len(c.Replies))
}

// CommandText returns a title for a command
func (whcb *WebhookContextBase) CommandText(title, icon string) string {
if title != "" {
if title != "" && !strings.HasPrefix(title, "/") {
title = whcb.Translate(title)
}
return CommandTextNoTrans(title, icon)
}

// CommandTextNoTrans returns a title for a command (pre-translated)
func CommandTextNoTrans(title, icon string) string {
if title == "" && icon != "" {
return icon
Expand All @@ -60,13 +72,15 @@ func CommandTextNoTrans(title, icon string) string {
}
}

// DefaultTitle returns a default title for a command in current locale
func (c Command) DefaultTitle(whc WebhookContext) string {
return c.TitleByKey(DEFAULT_TITLE, whc)
return c.TitleByKey(DefaultTitle, whc)
}

// TitleByKey returns a short/long title for a command in current locale
func (c Command) TitleByKey(key string, whc WebhookContext) string {
var title string
if key == DEFAULT_TITLE && c.Title != "" {
if key == DefaultTitle && c.Title != "" {
title = c.Title
} else if val, ok := c.Titles[key]; ok {
title = val
Expand Down
4 changes: 2 additions & 2 deletions core/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
var testCmd = Command{
Title: "Title1",
Titles: map[string]string{
SHORT_TITLE: "ttl1",
ShortTitle: "ttl1",
},
}

Expand All @@ -20,7 +20,7 @@ func TestCommand_DefaultTitle(t *testing.T) {
}

func TestCommand_TitleByKey(t *testing.T) {
if testCmd.TitleByKey(SHORT_TITLE, testWhc) != "ttl1" {
if testCmd.TitleByKey(ShortTitle, testWhc) != "ttl1" {
t.Error("Wrong title")
}
}
3 changes: 2 additions & 1 deletion core/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package bots

import "errors"

var NotImplementedError = errors.New("Not implemented")
// ErrNotImplemented if some feature is not implemented yet
var ErrNotImplemented = errors.New("Not implemented")

const (
MESSAGE_TEXT_I_DID_NOT_UNDERSTAND_THE_COMMAND = "MESSAGE_TEXT_I_DID_NOT_UNDERSTAND_THE_COMMAND"
Expand Down
29 changes: 20 additions & 9 deletions core/context.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
package bots

import (
"net/http"

"github.com/strongo/app"
"github.com/strongo/db"
"github.com/strongo/measurement-protocol"
"golang.org/x/net/context"
"net/http"
"github.com/strongo/gamp"
"context"
)

// WebhookInlineQueryContext provides context for inline query (TODO: check & document)
type WebhookInlineQueryContext interface {
}

type GaQueuer interface {// TODO: can be unexported?
Queue(message gamp.Message) error
}

// GaContext provides context to Google Analytics
type GaContext interface {
GaMeasurement() *measurement.BufferedSender
GaCommon() measurement.Common
GaEvent(category, action string) measurement.Event
GaEventWithLabel(category, action, label string) measurement.Event
GaMeasurement() GaQueuer
GaCommon() gamp.Common
GaEvent(category, action string) gamp.Event
GaEventWithLabel(category, action, label string) gamp.Event
}

// WebhookContext provides context for current request from user to bot
type WebhookContext interface {
// TODO: Make interface smaller?
GaContext
db.TransactionCoordinator
Environment() strongo.Environment
Expand Down Expand Up @@ -54,7 +63,6 @@ type WebhookContext interface {
NewEditMessage(text string, format MessageFormat) (MessageFromBot, error)
//NewEditMessageKeyboard(kbMarkup tgbotapi.InlineKeyboardMarkup) MessageFromBot

GetHttpClient() *http.Client
UpdateLastProcessed(chatEntity BotChat) error

AppUserIntID() int64
Expand All @@ -72,15 +80,18 @@ type WebhookContext interface {
Responder() WebhookResponder
}

// BotState provides state of the bot (TODO: document how is used)
type BotState interface {
IsNewerThen(chatEntity BotChat) bool
}

// BotInputProvider provides an input from a specific bot interface (Telegram, FB Messenger, Viber, etc.)
type BotInputProvider interface {
Input() WebhookInput
}

type BotApiUser interface {
// BotAPIUser provides info about current bot user
type BotAPIUser interface {
//IdAsString() string
//IdAsInt64() int64
FirstName() string
Expand Down
33 changes: 16 additions & 17 deletions core/context_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package bots
import (
"github.com/pkg/errors"
"github.com/strongo/log"
"golang.org/x/net/context"
"context"
)

// SetAccessGranted marks current context as authenticated
func SetAccessGranted(whc WebhookContext, value bool) (err error) {
c := whc.Context()
log.Debugf(c, "SetAccessGranted(value=%v)", value)
Expand Down Expand Up @@ -38,25 +39,23 @@ func SetAccessGranted(whc WebhookContext, value bool) (err error) {
log.Debugf(c, "SetAccessGranted(): whc.GetSender().GetID() = %v", botUserID)
if botUser, err := whc.GetBotUserById(c, botUserID); err != nil {
return errors.Wrapf(err, "Failed to get bot user by id=%v", botUserID)
} else if botUser.IsAccessGranted() == value {
log.Infof(c, "No need to change botUser.AccessGranted, as already is: %v", value)
} else {
if botUser.IsAccessGranted() == value {
log.Infof(c, "No need to change botUser.AccessGranted, as already is: %v", value)
} else {
err = whc.RunInTransaction(c, func(c context.Context) error {
botUser.SetAccessGranted(value)
if botUser, err = whc.GetBotUserById(c, botUserID); err != nil {
return errors.Wrapf(err, "Failed to get transactionally bot user by id=%v", botUserID)
}
if changed := botUser.SetAccessGranted(value); changed {
if err = whc.SaveBotUser(c, botUserID, botUser); err != nil {
err = errors.Wrapf(err, "Failed to call whc.SaveBotUser(botUserID=%v)", botUserID)
}
err = whc.RunInTransaction(c, func(c context.Context) error {
botUser.SetAccessGranted(value)
if botUser, err = whc.GetBotUserById(c, botUserID); err != nil {
return errors.Wrapf(err, "Failed to get transactionally bot user by id=%v", botUserID)
}
if changed := botUser.SetAccessGranted(value); changed {
if err = whc.SaveBotUser(c, botUserID, botUser); err != nil {
err = errors.Wrapf(err, "Failed to call whc.SaveBotUser(botUserID=%v)", botUserID)
}
return err
}, nil)
}
return err
}
return err
}, nil)
}
return err
//return SetAccessGrantedForAllUserChats(whc, whc.BotUserKey, value) // TODO: Call in deferrer
}

Expand Down
Loading

0 comments on commit 8ef5775

Please sign in to comment.