github.com/456vv/valexa@v1.0.2-0.20200706152242-1fb922d71ce5/EchoRequest.go (about)

     1  package valexa
     2  
     3  import (
     4  	"time"
     5  	"fmt"
     6  	
     7  )
     8  
     9  /*
    10  https://developer.amazon.com/zh/docs/custom-skills/request-and-response-json-reference.html
    11  
    12  POST / HTTP/1.1
    13  Content-Type : application/json;charset=UTF-8
    14  Host : your.application.endpoint
    15  Content-Length :
    16  Accept : application/json
    17  Accept-Charset : utf-8
    18  Signature: 
    19  SignatureCertChainUrl: https://s3.amazonaws.com/echo.api/echo-api-cert.pem
    20  Request Body Syntax
    21  
    22  {
    23    "version": "1.0",
    24    "session": {
    25      "new": true,
    26      "sessionId": "amzn1.echo-api.session.[unique-value-here]",
    27      "application": {
    28        "applicationId": "amzn1.ask.skill.[unique-value-here]"
    29      },
    30      "attributes": {
    31        "key": "string value"
    32      },
    33      "user": {
    34        "userId": "amzn1.ask.account.[unique-value-here]",
    35        "accessToken": "Atza|AAAAAAAA...",
    36        "permissions": {
    37          "consentToken": "ZZZZZZZ..."
    38        }
    39      }
    40    },
    41    "context": {
    42      "System": {
    43        "device": {
    44          "deviceId": "string",
    45          "supportedInterfaces": {
    46            "AudioPlayer": {}
    47          }
    48        },
    49        "application": {
    50          "applicationId": "amzn1.ask.skill.[unique-value-here]"
    51        },
    52        "user": {
    53          "userId": "amzn1.ask.account.[unique-value-here]",
    54          "accessToken": "Atza|AAAAAAAA...",
    55          "permissions": {
    56            "consentToken": "ZZZZZZZ..."
    57          }
    58        },
    59        "apiEndpoint": "https://api.amazonalexa.com",
    60        "apiAccessToken": "AxThk..."
    61      },
    62      "AudioPlayer": {
    63        "playerActivity": "PLAYING",
    64        "token": "audioplayer-token",
    65        "offsetInMilliseconds": 0
    66      }
    67    },
    68    "request": {
    69  	  "type": "IntentRequest",
    70  	  "requestId": "string",
    71  	  "timestamp": "string",
    72  	  "dialogState": "string",
    73  	  "locale": "string",
    74  	  "intent": {
    75  	    "name": "string",
    76  	    "confirmationStatus": "string",
    77  	    "slots": {
    78  	      "SlotName": {
    79  	        "name": "string",
    80  	        "value": "string",
    81  	        "confirmationStatus": "string",
    82  	        "resolutions": {
    83  	          "resolutionsPerAuthority": [
    84  	            {
    85  	              "authority": "string",
    86  	              "status": {
    87  	                "code": "string"
    88  	              },
    89  	              "values": [
    90  	                {
    91  	                  "value": {
    92  	                    "name": "string",
    93  	                    "id": "string"
    94  	                  }
    95  	                }
    96  	              ]
    97  	            }
    98  	          ]
    99  	        }
   100  	      }
   101  	    }
   102  	  }
   103    }
   104  }
   105  
   106  //IntentRequest Example
   107  {
   108    "version": "1.0",
   109    "session": {
   110      "new": false,
   111      "sessionId": "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000",
   112      "application": {
   113        "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
   114      },
   115      "attributes": {
   116        "supportedHoroscopePeriods": {
   117          "daily": true,
   118          "weekly": false,
   119          "monthly": false
   120        }
   121      },
   122      "user": {
   123        "userId": "amzn1.account.AM3B00000000000000000000000"
   124      }
   125    },
   126    "context": {
   127      "System": {
   128        "application": {
   129          "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
   130        },
   131        "user": {
   132          "userId": "amzn1.account.AM3B00000000000000000000000"
   133        },
   134        "device": {
   135          "supportedInterfaces": {
   136            "AudioPlayer": {}
   137          }
   138        }
   139      },
   140      "AudioPlayer": {
   141        "offsetInMilliseconds": 0,
   142        "playerActivity": "IDLE"
   143      }
   144    },
   145    "request": {
   146      "type": "IntentRequest",
   147      "requestId": " amzn1.echo-api.request.0000000-0000-0000-0000-00000000000",
   148      "timestamp": "2015-05-13T12:34:56Z",
   149      "dialogState": "COMPLETED",
   150      "locale": "string",
   151      "intent": {
   152        "name": "GetZodiacHoroscopeIntent",
   153        "confirmationStatus": "NONE"
   154        "slots": {
   155          "ZodiacSign": {
   156            "name": "ZodiacSign",
   157            "value": "virgo",
   158            "confirmationStatus": "NONE"
   159          }
   160        }
   161      }
   162    }
   163  }
   164  
   165  SessionEndedRequest:
   166  {
   167    "version": "1.0",
   168    "session": {
   169      "new": false,
   170      "sessionId": "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000",
   171      "application": {
   172        "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
   173      },
   174      "attributes": {
   175        "supportedHoroscopePeriods": {
   176          "daily": true,
   177          "weekly": false,
   178          "monthly": false
   179        }
   180      },
   181      "user": {
   182        "userId": "amzn1.account.AM3B00000000000000000000000"
   183      }
   184    },
   185    "context": {
   186      "System": {
   187        "application": {
   188          "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
   189        },
   190        "user": {
   191          "userId": "amzn1.account.AM3B00000000000000000000000"
   192        },
   193        "device": {
   194          "supportedInterfaces": {
   195            "AudioPlayer": {}
   196          }
   197        }
   198      },
   199      "AudioPlayer": {
   200        "offsetInMilliseconds": 0,
   201        "playerActivity": "IDLE"
   202      }
   203    },
   204    "request": {
   205      "type": "SessionEndedRequest",
   206      "requestId": "amzn1.echo-api.request.0000000-0000-0000-0000-00000000000",
   207      "timestamp": "2015-05-13T12:34:56Z",
   208      "reason": "USER_INITIATED",
   209      "locale": "string"
   210    }
   211  }
   212  */
   213  
   214  
   215  
   216  
   217  //提供AudioPlayer接口当前状态的对象
   218  //https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html#audioplayer-object
   219  type EchoRequestContextAudioPlayer struct {
   220   	//发送请求时的轨道偏移量(以毫秒为单位)。
   221   	//如果曲目在开头,这是0。AudioPlayer当您的技能是最近在设备上播放音频的技能时,这只会包含在对象中。
   222  	OffsetInMilliseconds int    										`json:"offsetInMilliseconds"`
   223  
   224  	//音频播放的最后已知状态。
   225  	//IDLE:没有什么,没有入队的项目。
   226  	//PAUSED:流已暂停。
   227  	//PLAYING:流正在播放。
   228  	//BUFFER_UNDERRUN:缓冲区不足
   229  	//FINISHED:流完了。STOPPED:流被中断。
   230  	PlayerActivity       string 										`json:"playerActivity"`
   231  
   232  	//音频流的不透明标记。发送Play指令时提供此标记。
   233  	//AudioPlayer当您的技能是最近在设备上播放音频的技能时,这只会包含在对象中。
   234  	Token                string 										`json:"token"`
   235  }
   236  
   237  type EchoRequestContextSystemApplication struct {
   238  	ApplicationID string 												`json:"applicationId"`
   239  }
   240  
   241  type EchoRequestContextSystemDeviceSupportedInterfaces struct {
   242  	AudioPlayer struct{} 												`json:"AudioPlayer"`
   243  }
   244  
   245  type EchoRequestContextSystemDevice struct {
   246  	DeviceID            string 												`json:"deviceId"`
   247  	SupportedInterfaces EchoRequestContextSystemDeviceSupportedInterfaces	`json:"supportedInterfaces"`
   248  }
   249  
   250  type EchoRequestContextSystemUserPermissions struct {
   251  	ConsentToken string 												`json:"consentToken"`
   252  }
   253  
   254  type EchoRequestContextSystemUser struct {
   255  	AccessToken string 													`json:"accessToken"`
   256  	Permissions EchoRequestContextSystemUserPermissions					`json:"permissions"`
   257  	UserID 		string 													`json:"userId"`
   258  }
   259  
   260  type EchoRequestContextSystem struct {
   261  	APIAccessToken 	string 												`json:"apiAccessToken"`
   262  	APIEndpoint   	string 												`json:"apiEndpoint"`
   263  	Application    	EchoRequestContextSystemApplication					`json:"application"`
   264  	Device			EchoRequestContextSystemDevice						`json:"device"`
   265  	User  			EchoRequestContextSystemUser						`json:"user"`
   266  }
   267  
   268  //Alexa服务和设备的当前状态的信息。用于在会话(的上下文中发送的请求LaunchRequest和IntentRequest)时,
   269  //context对象将复制user和application其也可在信息session对象。
   270  //https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html#context-object
   271  type EchoRequestContext struct {
   272  	AudioPlayer EchoRequestContextAudioPlayer							`json:"AudioPlayer"`
   273  	System  	EchoRequestContextSystem		 						`json:"System"`
   274  
   275  }
   276  
   277  type EchoRequestRequestError struct {
   278  	Message string 														`json:"message"`
   279  	Type    string 														`json:"type"`
   280  }
   281  
   282  type EchoRequestRequestIntentSlot struct {
   283  	ConfirmationStatus string   										`json:"confirmationStatus"`
   284  	Resolutions        struct{} 										`json:"resolutions"`
   285  	Name               string   										`json:"name"`
   286  	Value              string   										`json:"value"`
   287  }
   288  
   289  type EchoRequestRequestIntent struct {
   290  	ConfirmationStatus string 											`json:"confirmationStatus"`
   291  	Name               string 											`json:"name"`
   292  	Slots              map[string]*EchoRequestRequestIntentSlot			`json:"slots"`
   293  }
   294  
   295  type EchoRequestRequest	struct {
   296  	DialogState string 													`json:"dialogState"`
   297  	Error       EchoRequestRequestError									`json:"error"`
   298  	Intent  	EchoRequestRequestIntent								`json:"intent"`
   299  	Locale    	string 													`json:"locale"`
   300  	Reason    	string 													`json:"reason"`
   301  	RequestID 	string 													`json:"requestId"`
   302  	Timestamp 	string 													`json:"timestamp"`
   303  	Type      	string 													`json:"type"`
   304  }
   305  
   306  type EchoRequestSessionApplication struct {
   307  	ApplicationID string 												`json:"applicationId"`
   308  }
   309  
   310  type EchoRequestSessionUserPermissions struct {
   311  	ConsentToken string 												`json:"consentToken"`
   312  }
   313  type EchoRequestSessionUser struct {
   314  	AccessToken string 													`json:"accessToken"`
   315  	Permissions EchoRequestSessionUserPermissions						`json:"permissions"`
   316  	UserID 		string 													`json:"userId"`
   317  }
   318  type EchoRequestSession struct {
   319  	Application EchoRequestSessionApplication							`json:"application"`
   320  	Attributes	struct{} 												`json:"attributes"`
   321  	New       	bool     												`json:"new"`
   322  	SessionID 	string   												`json:"sessionId"`
   323  	User      	EchoRequestSessionUser									`json:"user"`
   324  }
   325  type EchoRequest struct {
   326  	Context	EchoRequestContext											`json:"context"`
   327  	Request EchoRequestRequest											`json:"request"`
   328  	Session EchoRequestSession											`json:"session"`
   329  	Version string 														`json:"version"`
   330  }
   331  
   332  //验证请求是否有效
   333  //	second int	允许过时多久?
   334  //	bool		true有效,false无效
   335  func (T *EchoRequest) VerifyTimestamp(second int) bool {
   336  	reqTimestamp, err := time.Parse(time.RFC3339, T.Request.Timestamp)
   337  	if err != nil {
   338  		return false
   339  	}
   340  	if time.Since(reqTimestamp) < time.Duration(second)*time.Second {
   341  		return true
   342  	}
   343  	return false
   344  }
   345  
   346  //读取语言类型
   347  //	string	语言类型
   348  func (T *EchoRequest) GetLocale() string {
   349  	return T.Request.Locale
   350  }
   351  
   352  //读取程序ID
   353  //	string	程序ID
   354  func (T *EchoRequest) GetApplicationID() string {
   355  	return T.Session.Application.ApplicationID
   356  }
   357  
   358  //读取本次会话的ID。如果用户结束会话,再发起会话,这个ID将是一个全新ID。
   359  //	string	会话ID
   360  func (T *EchoRequest) GetSessionID() string {
   361  	return T.Session.SessionID
   362  }
   363  
   364  //读取用户的ID
   365  //	string	用户ID
   366  func (T *EchoRequest) GetUserID() string {
   367  	return T.Session.User.UserID
   368  }
   369  
   370  //读取用户的令牌
   371  //	string	令牌
   372  func (T *EchoRequest) GetAccessToken() string {
   373  	return T.Session.User.AccessToken
   374  }
   375  
   376  
   377  //读取意图类型,有效:LaunchRequest, IntentRequest, SessionEndedRequest
   378  //	string	意图类型
   379  func (T *EchoRequest) GetRequestType() string {
   380  	return T.Request.Type
   381  }
   382  
   383  //读取意图名称,如标注符:{Map}
   384  //	string	意图名称
   385  func (T *EchoRequest) GetIntentName() string {
   386  	if T.GetRequestType() == "IntentRequest" {
   387  		return T.Request.Intent.Name
   388  	}
   389  	return ""
   390  }
   391  
   392  //读取出所有Solt对象,所有值,包含空值
   393  //	slots	所有跟踪名称和值
   394  //	err		错误,如果不是意图类型请求,调用这个方法,将会返回错误
   395  func (T *EchoRequest) GetSlots() (slots map[string]*EchoRequestRequestIntentSlot, err error) {
   396  	if T.GetRequestType() != "IntentRequest" {
   397  		return  nil, fmt.Errorf("valexa: 此意图类型不支持读取插槽,仅支持IntentRequest类型。")
   398  	}
   399  
   400  	slots = T.Request.Intent.Slots
   401  	if slots == nil {
   402  		return  nil, fmt.Errorf("valexa: 插槽为nil")
   403  	}
   404  	return
   405  }
   406  
   407  //读取出所有Solt对象,非空值的
   408  //	slots	所有跟踪名称和值
   409  //	err		错误,如果不是意图类型请求,调用这个方法,将会返回错误
   410  func (T *EchoRequest) GetValueSlots() (slots map[string]*EchoRequestRequestIntentSlot, err error) {
   411  	gslots, err := T.GetSlots()
   412  	if err != nil {
   413  		return
   414  	}
   415  	slots = make(map[string]*EchoRequestRequestIntentSlot)
   416  	for key, slot := range gslots {
   417  		if slot.Value != "" {
   418  			slots[key] = slot
   419  		}
   420  	}
   421  	return slots, nil
   422  }
   423  
   424  
   425  
   426  //读取出所有Solt名称
   427  //	names	所有跟踪名称
   428  func (T *EchoRequest) GetSlotNames() (names []string) {
   429  	names = []string{}
   430  	slots, err := T.GetSlots()
   431  	if err != nil {
   432  		return
   433  	}
   434  	for k, _ := range slots {
   435  		names = append(names, k)
   436  	}
   437  	return
   438  }
   439  
   440  //读取Solt值
   441  //	slotName	跟踪名称
   442  //	val			跟踪的值
   443  //	err			错误,如果这个名称不存在,将会返回错误
   444  func (T *EchoRequest) GetSlotValue(slotName string) (val string, err error) {
   445  	slots, err := T.GetSlots()
   446  	if err != nil {
   447  		return
   448  	}
   449  	if slot, ok := slots[slotName]; ok {
   450  		return slot.Value, nil
   451  	}
   452  	return "", fmt.Errorf("valexa: 名称(%s)没有找到匹配 Solt !", slotName)
   453  }
   454  
   455  //读取Solt对象
   456  //	slotName	跟踪名称
   457  //	slot		跟踪的对象
   458  //	err			错误,如果这个名称不存在,将会返回错误
   459  func (T *EchoRequest) GetSlot(slotName string) (slot *EchoRequestRequestIntentSlot, err error) {
   460  	slots, err := T.GetSlots()
   461  	if err != nil {
   462  		return
   463  	}
   464  	slot, ok := slots[slotName]
   465  	if ok {
   466  		return
   467  	}
   468  	return nil, fmt.Errorf("valexa: 名称(%s)没有找到匹配 Solt !", slotName)
   469  }