github.com/line/line-bot-sdk-go/v7@v7.21.0/linebot/event.go (about) 1 // Copyright 2016 LINE Corporation 2 // 3 // LINE Corporation licenses this file to you under the Apache License, 4 // version 2.0 (the "License"); you may not use this file except in compliance 5 // with the License. You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package linebot 16 17 import ( 18 "encoding/hex" 19 "encoding/json" 20 "time" 21 ) 22 23 // EventType type 24 type EventType string 25 26 // EventType constants 27 const ( 28 EventTypeMessage EventType = "message" 29 EventTypeFollow EventType = "follow" 30 EventTypeUnfollow EventType = "unfollow" 31 EventTypeJoin EventType = "join" 32 EventTypeLeave EventType = "leave" 33 EventTypeMemberJoined EventType = "memberJoined" 34 EventTypeMemberLeft EventType = "memberLeft" 35 EventTypePostback EventType = "postback" 36 EventTypeBeacon EventType = "beacon" 37 EventTypeAccountLink EventType = "accountLink" 38 EventTypeThings EventType = "things" 39 EventTypeUnsend EventType = "unsend" 40 EventTypeVideoPlayComplete EventType = "videoPlayComplete" 41 ) 42 43 // EventMode type 44 type EventMode string 45 46 // EventMode constants 47 const ( 48 EventModeActive EventMode = "active" 49 EventModeStandby EventMode = "standby" 50 ) 51 52 // EventSourceType type 53 type EventSourceType string 54 55 // EventSourceType constants 56 const ( 57 EventSourceTypeUser EventSourceType = "user" 58 EventSourceTypeGroup EventSourceType = "group" 59 EventSourceTypeRoom EventSourceType = "room" 60 ) 61 62 // EventSource type 63 type EventSource struct { 64 Type EventSourceType `json:"type"` 65 UserID string `json:"userId,omitempty"` 66 GroupID string `json:"groupId,omitempty"` 67 RoomID string `json:"roomId,omitempty"` 68 } 69 70 // Params type 71 type Params struct { 72 Date string `json:"date,omitempty"` 73 Time string `json:"time,omitempty"` 74 Datetime string `json:"datetime,omitempty"` 75 NewRichMenuAliasID string `json:"newRichMenuAliasId,omitempty"` 76 Status string `json:"status,omitempty"` 77 } 78 79 // Members type 80 type Members struct { 81 Members []EventSource `json:"members"` 82 } 83 84 // Postback type 85 type Postback struct { 86 Data string `json:"data"` 87 Params *Params `json:"params,omitempty"` 88 } 89 90 // BeaconEventType type 91 type BeaconEventType string 92 93 // BeaconEventType constants 94 const ( 95 BeaconEventTypeEnter BeaconEventType = "enter" 96 BeaconEventTypeLeave BeaconEventType = "leave" 97 BeaconEventTypeBanner BeaconEventType = "banner" 98 BeaconEventTypeStay BeaconEventType = "stay" 99 ) 100 101 // Beacon type 102 type Beacon struct { 103 Hwid string 104 Type BeaconEventType 105 DeviceMessage []byte 106 } 107 108 // AccountLinkResult type 109 type AccountLinkResult string 110 111 // AccountLinkResult constants 112 const ( 113 AccountLinkResultOK AccountLinkResult = "ok" 114 AccountLinkResultFailed AccountLinkResult = "failed" 115 ) 116 117 // AccountLink type 118 type AccountLink struct { 119 Result AccountLinkResult 120 Nonce string 121 } 122 123 // ThingsResult type 124 type ThingsResult struct { 125 ScenarioID string 126 Revision int 127 StartTime int64 128 EndTime int64 129 ResultCode ThingsResultCode 130 ActionResults []*ThingsActionResult 131 BLENotificationPayload []byte 132 ErrorReason string 133 } 134 135 // ThingsResultCode type 136 type ThingsResultCode string 137 138 // ThingsResultCode constants 139 const ( 140 ThingsResultCodeSuccess ThingsResultCode = "success" 141 ThingsResultCodeGattError ThingsResultCode = "gatt_error" 142 ThingsResultCodeRuntimeError ThingsResultCode = "runtime_error" 143 ) 144 145 // ThingsActionResult type 146 type ThingsActionResult struct { 147 Type ThingsActionResultType 148 Data []byte 149 } 150 151 // ThingsActionResultType type 152 type ThingsActionResultType string 153 154 // ThingsActionResultType constants 155 const ( 156 ThingsActionResultTypeBinary ThingsActionResultType = "binary" 157 ThingsActionResultTypeVoid ThingsActionResultType = "void" 158 ) 159 160 // Things type 161 type Things struct { 162 DeviceID string 163 Type string 164 Result *ThingsResult 165 } 166 167 // Unsend type 168 type Unsend struct { 169 MessageID string `json:"messageId"` 170 } 171 172 // VideoPlayComplete type 173 type VideoPlayComplete struct { 174 TrackingID string `json:"trackingId"` 175 } 176 177 // StickerResourceType type 178 type StickerResourceType string 179 180 // StickerResourceType constants 181 const ( 182 StickerResourceTypeStatic StickerResourceType = "STATIC" 183 StickerResourceTypeAnimation StickerResourceType = "ANIMATION" 184 StickerResourceTypeSound StickerResourceType = "SOUND" 185 StickerResourceTypeAnimationSound StickerResourceType = "ANIMATION_SOUND" 186 StickerResourceTypePerStickerText StickerResourceType = "MESSAGE" 187 StickerResourceTypePopup StickerResourceType = "POPUP" 188 StickerResourceTypePopupSound StickerResourceType = "POPUP_SOUND" 189 StickerResourceTypeNameText StickerResourceType = "CUSTOM" 190 ) 191 192 // DeliveryContext type 193 type DeliveryContext struct { 194 IsRedelivery bool `json:"isRedelivery"` 195 } 196 197 // Event type 198 type Event struct { 199 ReplyToken string 200 Type EventType 201 Mode EventMode 202 Timestamp time.Time 203 Source *EventSource 204 Message Message 205 Joined *Members 206 Left *Members 207 Postback *Postback 208 Beacon *Beacon 209 AccountLink *AccountLink 210 Things *Things 211 Members []*EventSource 212 Unsend *Unsend 213 VideoPlayComplete *VideoPlayComplete 214 WebhookEventID string 215 DeliveryContext DeliveryContext 216 } 217 218 type rawEvent struct { 219 ReplyToken string `json:"replyToken,omitempty"` 220 Type EventType `json:"type"` 221 Mode EventMode `json:"mode"` 222 Timestamp int64 `json:"timestamp"` 223 Source *EventSource `json:"source"` 224 Message *rawEventMessage `json:"message,omitempty"` 225 Postback *Postback `json:"postback,omitempty"` 226 Beacon *rawBeaconEvent `json:"beacon,omitempty"` 227 AccountLink *rawAccountLinkEvent `json:"link,omitempty"` 228 Joined *rawMemberEvent `json:"joined,omitempty"` 229 Left *rawMemberEvent `json:"left,omitempty"` 230 Things *rawThingsEvent `json:"things,omitempty"` 231 Unsend *Unsend `json:"unsend,omitempty"` 232 VideoPlayComplete *VideoPlayComplete `json:"videoPlayComplete,omitempty"` 233 WebhookEventID string `json:"webhookEventId"` 234 DeliveryContext DeliveryContext `json:"deliveryContext"` 235 } 236 237 type rawMemberEvent struct { 238 Members []*EventSource `json:"members"` 239 } 240 241 type rawEventMessage struct { 242 ID string `json:"id"` 243 Type MessageType `json:"type"` 244 Text string `json:"text,omitempty"` 245 Duration int `json:"duration,omitempty"` 246 Title string `json:"title,omitempty"` 247 Address string `json:"address,omitempty"` 248 FileName string `json:"fileName,omitempty"` 249 FileSize int `json:"fileSize,omitempty"` 250 Latitude float64 `json:"latitude,omitempty"` 251 Longitude float64 `json:"longitude,omitempty"` 252 PackageID string `json:"packageId,omitempty"` 253 StickerID string `json:"stickerId,omitempty"` 254 ContentProvider *ContentProvider `json:"contentProvider,omitempty"` 255 ImageSet *ImageSet `json:"imageSet,omitempty"` 256 StickerResourceType StickerResourceType `json:"stickerResourceType,omitempty"` 257 Keywords []string `json:"keywords,omitempty"` 258 Emojis []*Emoji `json:"emojis,omitempty"` 259 Mention *Mention `json:"mention,omitempty"` 260 } 261 262 type rawBeaconEvent struct { 263 Hwid string `json:"hwid"` 264 Type BeaconEventType `json:"type"` 265 DM string `json:"dm,omitempty"` 266 } 267 268 type rawAccountLinkEvent struct { 269 Result AccountLinkResult `json:"result"` 270 Nonce string `json:"nonce"` 271 } 272 273 type rawThingsResult struct { 274 ScenarioID string `json:"scenarioId"` 275 Revision int `json:"revision"` 276 StartTime int64 `json:"startTime"` 277 EndTime int64 `json:"endTime"` 278 ResultCode ThingsResultCode `json:"resultCode"` 279 ActionResults []*rawThingsActionResult `json:"actionResults"` 280 BLENotificationPayload string `json:"bleNotificationPayload,omitempty"` 281 ErrorReason string `json:"errorReason,omitempty"` 282 } 283 284 type rawThingsActionResult struct { 285 Type ThingsActionResultType `json:"type,omitempty"` 286 Data string `json:"data,omitempty"` 287 } 288 289 type rawThingsEvent struct { 290 DeviceID string `json:"deviceId"` 291 Type string `json:"type"` 292 Result *rawThingsResult `json:"result,omitempty"` 293 } 294 295 const ( 296 milliSecPerSec = int64(time.Second / time.Millisecond) 297 nanoSecPerMilliSec = int64(time.Millisecond / time.Nanosecond) 298 ) 299 300 // MarshalJSON method of Event 301 func (e *Event) MarshalJSON() ([]byte, error) { 302 raw := rawEvent{ 303 ReplyToken: e.ReplyToken, 304 Type: e.Type, 305 Mode: e.Mode, 306 Timestamp: e.Timestamp.Unix()*milliSecPerSec + int64(e.Timestamp.Nanosecond())/int64(time.Millisecond), 307 Source: e.Source, 308 Postback: e.Postback, 309 Unsend: e.Unsend, 310 VideoPlayComplete: e.VideoPlayComplete, 311 WebhookEventID: e.WebhookEventID, 312 DeliveryContext: e.DeliveryContext, 313 } 314 if e.Beacon != nil { 315 raw.Beacon = &rawBeaconEvent{ 316 Hwid: e.Beacon.Hwid, 317 Type: e.Beacon.Type, 318 DM: hex.EncodeToString(e.Beacon.DeviceMessage), 319 } 320 } 321 if e.AccountLink != nil { 322 raw.AccountLink = &rawAccountLinkEvent{ 323 Result: e.AccountLink.Result, 324 Nonce: e.AccountLink.Nonce, 325 } 326 } 327 328 switch e.Type { 329 case EventTypeMemberJoined: 330 raw.Joined = &rawMemberEvent{ 331 Members: e.Members, 332 } 333 case EventTypeMemberLeft: 334 raw.Left = &rawMemberEvent{ 335 Members: e.Members, 336 } 337 case EventTypeThings: 338 raw.Things = &rawThingsEvent{ 339 DeviceID: e.Things.DeviceID, 340 Type: e.Things.Type, 341 } 342 if e.Things.Result != nil { 343 raw.Things.Result = &rawThingsResult{ 344 ScenarioID: e.Things.Result.ScenarioID, 345 Revision: e.Things.Result.Revision, 346 StartTime: e.Things.Result.StartTime, 347 EndTime: e.Things.Result.EndTime, 348 ResultCode: e.Things.Result.ResultCode, 349 350 BLENotificationPayload: string(e.Things.Result.BLENotificationPayload), 351 ErrorReason: e.Things.Result.ErrorReason, 352 } 353 if e.Things.Result.ActionResults != nil { 354 raw.Things.Result.ActionResults = make([]*rawThingsActionResult, len(e.Things.Result.ActionResults)) 355 } 356 for i := range e.Things.Result.ActionResults { 357 raw.Things.Result.ActionResults[i] = &rawThingsActionResult{ 358 Type: e.Things.Result.ActionResults[i].Type, 359 Data: string(e.Things.Result.ActionResults[i].Data), 360 } 361 } 362 } 363 } 364 365 switch m := e.Message.(type) { 366 case *TextMessage: 367 raw.Message = &rawEventMessage{ 368 Type: MessageTypeText, 369 ID: m.ID, 370 Text: m.Text, 371 Emojis: m.Emojis, 372 Mention: m.Mention, 373 } 374 case *ImageMessage: 375 raw.Message = &rawEventMessage{ 376 Type: MessageTypeImage, 377 ID: m.ID, 378 ContentProvider: m.ContentProvider, 379 ImageSet: m.ImageSet, 380 } 381 case *VideoMessage: 382 raw.Message = &rawEventMessage{ 383 Type: MessageTypeVideo, 384 ID: m.ID, 385 Duration: m.Duration, 386 ContentProvider: m.ContentProvider, 387 } 388 case *AudioMessage: 389 raw.Message = &rawEventMessage{ 390 Type: MessageTypeAudio, 391 ID: m.ID, 392 Duration: m.Duration, 393 ContentProvider: m.ContentProvider, 394 } 395 case *FileMessage: 396 raw.Message = &rawEventMessage{ 397 Type: MessageTypeFile, 398 ID: m.ID, 399 FileName: m.FileName, 400 FileSize: m.FileSize, 401 } 402 case *LocationMessage: 403 raw.Message = &rawEventMessage{ 404 Type: MessageTypeLocation, 405 ID: m.ID, 406 Title: m.Title, 407 Address: m.Address, 408 Latitude: m.Latitude, 409 Longitude: m.Longitude, 410 } 411 case *StickerMessage: 412 raw.Message = &rawEventMessage{ 413 Type: MessageTypeSticker, 414 ID: m.ID, 415 PackageID: m.PackageID, 416 StickerID: m.StickerID, 417 StickerResourceType: m.StickerResourceType, 418 Keywords: m.Keywords, 419 Text: m.Text, 420 } 421 } 422 return json.Marshal(&raw) 423 } 424 425 // UnmarshalJSON method of Event 426 func (e *Event) UnmarshalJSON(body []byte) (err error) { 427 rawEvent := rawEvent{} 428 if err = json.Unmarshal(body, &rawEvent); err != nil { 429 return 430 } 431 432 e.ReplyToken = rawEvent.ReplyToken 433 e.Type = rawEvent.Type 434 e.Mode = rawEvent.Mode 435 e.Timestamp = time.Unix(rawEvent.Timestamp/milliSecPerSec, (rawEvent.Timestamp%milliSecPerSec)*nanoSecPerMilliSec).UTC() 436 e.Source = rawEvent.Source 437 e.WebhookEventID = rawEvent.WebhookEventID 438 e.DeliveryContext = rawEvent.DeliveryContext 439 440 switch rawEvent.Type { 441 case EventTypeMessage: 442 switch rawEvent.Message.Type { 443 case MessageTypeText: 444 e.Message = &TextMessage{ 445 ID: rawEvent.Message.ID, 446 Text: rawEvent.Message.Text, 447 Emojis: rawEvent.Message.Emojis, 448 Mention: rawEvent.Message.Mention, 449 } 450 case MessageTypeImage: 451 e.Message = &ImageMessage{ 452 ID: rawEvent.Message.ID, 453 ContentProvider: rawEvent.Message.ContentProvider, 454 ImageSet: rawEvent.Message.ImageSet, 455 } 456 case MessageTypeVideo: 457 e.Message = &VideoMessage{ 458 ID: rawEvent.Message.ID, 459 Duration: rawEvent.Message.Duration, 460 ContentProvider: rawEvent.Message.ContentProvider, 461 } 462 case MessageTypeAudio: 463 e.Message = &AudioMessage{ 464 ID: rawEvent.Message.ID, 465 Duration: rawEvent.Message.Duration, 466 ContentProvider: rawEvent.Message.ContentProvider, 467 } 468 case MessageTypeFile: 469 e.Message = &FileMessage{ 470 ID: rawEvent.Message.ID, 471 FileName: rawEvent.Message.FileName, 472 FileSize: rawEvent.Message.FileSize, 473 } 474 case MessageTypeLocation: 475 e.Message = &LocationMessage{ 476 ID: rawEvent.Message.ID, 477 Title: rawEvent.Message.Title, 478 Address: rawEvent.Message.Address, 479 Latitude: rawEvent.Message.Latitude, 480 Longitude: rawEvent.Message.Longitude, 481 } 482 case MessageTypeSticker: 483 e.Message = &StickerMessage{ 484 ID: rawEvent.Message.ID, 485 PackageID: rawEvent.Message.PackageID, 486 StickerID: rawEvent.Message.StickerID, 487 StickerResourceType: rawEvent.Message.StickerResourceType, 488 Keywords: rawEvent.Message.Keywords, 489 Text: rawEvent.Message.Text, 490 } 491 } 492 case EventTypePostback: 493 e.Postback = rawEvent.Postback 494 case EventTypeBeacon: 495 var deviceMessage []byte 496 deviceMessage, err = hex.DecodeString(rawEvent.Beacon.DM) 497 if err != nil { 498 return 499 } 500 e.Beacon = &Beacon{ 501 Hwid: rawEvent.Beacon.Hwid, 502 Type: rawEvent.Beacon.Type, 503 DeviceMessage: deviceMessage, 504 } 505 case EventTypeAccountLink: 506 e.AccountLink = &AccountLink{ 507 Result: rawEvent.AccountLink.Result, 508 Nonce: rawEvent.AccountLink.Nonce, 509 } 510 case EventTypeMemberJoined: 511 e.Members = rawEvent.Joined.Members 512 case EventTypeMemberLeft: 513 e.Members = rawEvent.Left.Members 514 case EventTypeThings: 515 e.Things = &Things{ 516 Type: rawEvent.Things.Type, 517 DeviceID: rawEvent.Things.DeviceID, 518 } 519 if rawEvent.Things.Result != nil { 520 rawResult := rawEvent.Things.Result 521 e.Things.Result = &ThingsResult{ 522 ScenarioID: rawResult.ScenarioID, 523 Revision: rawResult.Revision, 524 StartTime: rawResult.StartTime, 525 EndTime: rawResult.EndTime, 526 ResultCode: rawResult.ResultCode, 527 ActionResults: make([]*ThingsActionResult, len(rawResult.ActionResults)), 528 BLENotificationPayload: []byte(rawResult.BLENotificationPayload), 529 ErrorReason: rawResult.ErrorReason, 530 } 531 for i := range rawResult.ActionResults { 532 e.Things.Result.ActionResults[i] = &ThingsActionResult{ 533 Type: rawResult.ActionResults[i].Type, 534 Data: []byte(rawResult.ActionResults[i].Data), 535 } 536 } 537 } 538 case EventTypeUnsend: 539 e.Unsend = rawEvent.Unsend 540 case EventTypeVideoPlayComplete: 541 e.VideoPlayComplete = rawEvent.VideoPlayComplete 542 } 543 return 544 }