Skip to content

Commit

Permalink
Merge pull request #1 from ifedor/feature/session_state_implementation
Browse files Browse the repository at this point in the history
added session state implementation
  • Loading branch information
azzzak authored Jul 28, 2020
2 parents e95de36 + 7c21455 commit b2abde4
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 0 deletions.
23 changes: 23 additions & 0 deletions request.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package alice

import (
"encoding/json"
"errors"
"strings"
)
Expand Down Expand Up @@ -49,6 +50,10 @@ type Request struct {
UserID string `json:"user_id"`
} `json:"session"`

State struct {
Session interface{} `json:"session,omitempty"`
} `json:"state,omitempty"`

Version string `json:"version"`
Bearer string
}
Expand Down Expand Up @@ -190,6 +195,24 @@ func (req *Request) Ver() string {
return req.Version
}

// State.Session Состояние сессии.
func (req *Request) StateSession(key string) interface{} {
if req.State.Session == nil {
return nil
}
session := req.State.Session.(map[string]interface{})

return session[key]
}

// State.Session Состояние сессии json строкой
func (req *Request) StateSessionAsJson() (string, error) {
data, err := json.Marshal(req.State.Session)

return string(data), err
}


// AuthToken токен, полученный при связке аккаунтов.
func (req *Request) AuthToken() string {
if req.Bearer != "" {
Expand Down
46 changes: 46 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,12 +487,58 @@ func TestRequest_Ver(t *testing.T) {
}
}

func TestRequest_StateSession(t *testing.T) {
tests := map[string]struct {
request *alice.Request
want interface{}
}{
"when state is empty 0": {
request: getReq(0),
want: nil,
},
"when state is empty 1":{
request: getReq(1),
want: nil,
},
"when state is empty 2":{
request: getReq(2),
want: nil,
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
req := tt.request
got := req.StateSession("");
if !assert.Equal(t, tt.want, got) {
t.Errorf("Request.StateSession() = %v, want %v", got, tt.want)
}

})
}
t.Run("when state is struct", func(t *testing.T) {
req := getReq(3)
want := make(map[string]interface{})
want["int_value"] = 42

assert.Equal(t, 42.0, req.StateSession("int_value"))
assert.Equal(t, "exampleString", req.StateSession("string_value"))
assert.Equal(t, []interface{}{1.0,2.0,3.0,4.0}, req.StateSession("array_value"))
assert.Equal(t, map[string]interface{}{"one":"one"}, req.StateSession("struct_value"))
stateJson, err := req.StateSessionAsJson()
if assert.NoError(t, err) {
assert.Equal(t, `{"array_value":[1,2,3,4],"int_value":42,"string_value":"exampleString","struct_value":{"one":"one"}}`, stateJson)
}
})
}

func getReq(n int) *alice.Request {
source := []string{`{"meta":{"client_id":"ru.yandex.searchplugin/7.16 (none none; android 4.4.2)","interfaces":{"account_linking":{},"payments":{},"screen":{}},"locale":"ru-RU","timezone":"UTC"},"request":{"command":"съешь еще этих мягких французских булок","nlu":{"entities":[],"tokens":["съешь","еще","этих","мягких","французских","булок"]},"original_utterance":"съешь еще этих мягких французских булок","type":"SimpleUtterance"},"session":{"message_id":0,"new":true,"session_id":"e19e8eee-ae065e8-36e3f907-567a814b","skill_id":"e03f8d5b-35ef-4d57-9450-b721ca17a6c3","user_id":"03B1D487CAA1C7EBF80A195491B78ACA0AC9934CDFB12A29D063A8329BC42BF0"},"version":"1.0"}`,

`{"meta":{"client_id":"ru.yandex.searchplugin/7.16 (none none; android 4.4.2)","interfaces":{"account_linking":{},"payments":{}},"locale":"ru-RU","timezone":"UTC"},"request":{"nlu":{"entities":[],"tokens":[]},"payload":{"msg":"ok"},"type":"ButtonPressed"},"session":{"message_id":1,"new":false,"session_id":"eeb9fa7f-940e2502-1fbf9dfb-9448a1a9","skill_id":"e03f8d5b-35ef-4d57-9450-b721ca17a6c3","user_id":"03B1D487CAA1C7EBF80A195491B78ACA0AC9934CDFB12A29D063A8329BC42BF0"},"version":"1.0"}`,

`{"meta":{"client_id":"ru.yandex.searchplugin/7.16 (none none; android 4.4.2)","interfaces":{"account_linking":{},"payments":{}},"locale":"ru-RU","timezone":"UTC"},"request":{"nlu":{"entities":[],"tokens":[]},"payload":"msg","type":"ButtonPressed"},"session":{"message_id":1,"new":false,"session_id":"eeb9fa7f-940e2502-1fbf9dfb-9448a1a9","skill_id":"e03f8d5b-35ef-4d57-9450-b721ca17a6c3","user_id":"03B1D487CAA1C7EBF80A195491B78ACA0AC9934CDFB12A29D063A8329BC42BF0"},"version":"1.0"}`,

`{"meta":{"client_id":"ru.yandex.searchplugin/7.16 (none none; android 4.4.2)","interfaces":{"account_linking":{},"payments":{}},"locale":"ru-RU","timezone":"UTC"},"request":{"nlu":{"entities":[],"tokens":[]},"payload":"msg","type":"ButtonPressed"},"session":{"message_id":1,"new":false,"session_id":"eeb9fa7f-940e2502-1fbf9dfb-9448a1a9","skill_id":"e03f8d5b-35ef-4d57-9450-b721ca17a6c3","user_id":"03B1D487CAA1C7EBF80A195491B78ACA0AC9934CDFB12A29D063A8329BC42BF0"},"state":{"session":{"array_value":[1,2,3,4],"int_value":42,"string_value":"exampleString","struct_value":{"one":"one"}}},"version":"1.0"}`,
}

var req = new(alice.Request)
Expand Down
20 changes: 20 additions & 0 deletions response.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package alice

import (
"errors"
"fmt"
"math/rand"
"strings"
Expand All @@ -26,6 +27,8 @@ type Response struct {
UserID string `json:"user_id"`
} `json:"session"`

SessionState interface{} `json:"session_state,omitempty"`

Version string `json:"version"`
}

Expand All @@ -38,6 +41,7 @@ func (resp *Response) clean() *Response {
EndSession bool `json:"end_session"`
}{}
resp.StartAccountLinking = nil
resp.SessionState = nil
return resp
}

Expand Down Expand Up @@ -218,3 +222,19 @@ func (resp *Response) RandomPhrase(p ...Phrase) *Response {
resp.Response.TTS += p[ix].TTS
return resp
}

// AddSessionState добавляет па
func (resp *Response) AddSessionState(key string, data interface{}) error {
if resp.SessionState == nil {
resp.SessionState = make(map[string]interface{})
}

if stateBag, ok := resp.SessionState.(map[string]interface{}); ok {
stateBag[key] = data
resp.SessionState = stateBag
} else {
return errors.New(fmt.Sprintf("session_state: can't set data because session_state have type %T",
resp.SessionState))
}
return nil
}
16 changes: 16 additions & 0 deletions response_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,22 @@ func TestResponse_RandomPhrase(t *testing.T) {
}
}

func TestResponse_AddSessionState(t *testing.T) {
wantResp := getResp(0)
state := make(map[string]interface{})
state["one"] = struct{}{}
state["two"] = "twotwo"
wantResp.SessionState = state

resp := getResp(0)
err := resp.AddSessionState("one", struct{}{})
assert.NoError(t, err)
err = resp.AddSessionState("two", "twotwo")
if assert.NoError(t, err) {
assert.Equal(t, wantResp, resp)
}
}

func getResp(n int) *alice.Response {
source := []string{`{"response":{"text":"","end_session":true},"session":{"message_id":0,"session_id":"","user_id":""},"version":"1.0"}`,

Expand Down

0 comments on commit b2abde4

Please sign in to comment.