packages feed

line-bot-sdk 0.1.0.0 → 0.2.0.0

raw patch · 9 files changed

+412/−338 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Line.Bot.Client: Action :: Maybe URL -> Action -> QuickReplyButton
- Line.Bot.Client: ActionCamera :: Text -> Action
- Line.Bot.Client: ActionCameraRoll :: Text -> Action
- Line.Bot.Client: ActionLocation :: Text -> Action
- Line.Bot.Client: ActionMessage :: Text -> Text -> Action
- Line.Bot.Client: ActionPostback :: Text -> Text -> Text -> Action
- Line.Bot.Client: ActionURI :: Text -> Text -> Action
- Line.Bot.Client: Audio :: URL -> Int -> Maybe QuickReply -> Message
- Line.Bot.Client: ChannelToken :: Text -> ChannelToken
- Line.Bot.Client: Group :: ChatType
- Line.Bot.Client: Image :: URL -> URL -> Maybe QuickReply -> Message
- Line.Bot.Client: Location :: Text -> Text -> Double -> Double -> Maybe QuickReply -> Message
- Line.Bot.Client: MulticastMessageBody :: [Id User] -> [Message] -> MulticastMessageBody
- Line.Bot.Client: Profile :: Text -> Id User -> URL -> Maybe Text -> Profile
- Line.Bot.Client: PushMessageBody :: Id a -> [Message] -> PushMessageBody
- Line.Bot.Client: QuickReply :: [QuickReplyButton] -> QuickReply
- Line.Bot.Client: ReplyMessageBody :: ReplyToken -> [Message] -> ReplyMessageBody
- Line.Bot.Client: ReplyToken :: Text -> ReplyToken
- Line.Bot.Client: Room :: ChatType
- Line.Bot.Client: Sticker :: Text -> Text -> Maybe QuickReply -> Message
- Line.Bot.Client: Text :: Text -> Maybe QuickReply -> Message
- Line.Bot.Client: URL :: Text -> URL
- Line.Bot.Client: User :: ChatType
- Line.Bot.Client: Video :: URL -> URL -> Maybe QuickReply -> Message
- Line.Bot.Client: [$sel:action:Action] :: QuickReplyButton -> Action
- Line.Bot.Client: [$sel:address:Text] :: Message -> Text
- Line.Bot.Client: [$sel:displayName:Profile] :: Profile -> Text
- Line.Bot.Client: [$sel:displayText:ActionPostback] :: Action -> Text
- Line.Bot.Client: [$sel:duration:Text] :: Message -> Int
- Line.Bot.Client: [$sel:imageUrl:Action] :: QuickReplyButton -> Maybe URL
- Line.Bot.Client: [$sel:items:QuickReply] :: QuickReply -> [QuickReplyButton]
- Line.Bot.Client: [$sel:label:ActionPostback] :: Action -> Text
- Line.Bot.Client: [$sel:latitude:Text] :: Message -> Double
- Line.Bot.Client: [$sel:longitude:Text] :: Message -> Double
- Line.Bot.Client: [$sel:originalContentUrl:Text] :: Message -> URL
- Line.Bot.Client: [$sel:packageId:Text] :: Message -> Text
- Line.Bot.Client: [$sel:pictureUrl:Profile] :: Profile -> URL
- Line.Bot.Client: [$sel:postbackData:ActionPostback] :: Action -> Text
- Line.Bot.Client: [$sel:previewImageUrl:Text] :: Message -> URL
- Line.Bot.Client: [$sel:quickReply:Text] :: Message -> Maybe QuickReply
- Line.Bot.Client: [$sel:statusMessage:Profile] :: Profile -> Maybe Text
- Line.Bot.Client: [$sel:stickerId:Text] :: Message -> Text
- Line.Bot.Client: [$sel:text:ActionPostback] :: Action -> Text
- Line.Bot.Client: [$sel:text:Text] :: Message -> Text
- Line.Bot.Client: [$sel:title:Text] :: Message -> Text
- Line.Bot.Client: [$sel:uri:ActionPostback] :: Action -> Text
- Line.Bot.Client: [$sel:userId:Profile] :: Profile -> Id User
- Line.Bot.Client: [GroupId] :: Text -> Id Group
- Line.Bot.Client: [RoomId] :: Text -> Id Room
- Line.Bot.Client: [UserId] :: Text -> Id User
- Line.Bot.Client: data Action
- Line.Bot.Client: data ChatType
- Line.Bot.Client: data Id :: ChatType -> *
- Line.Bot.Client: data Message
- Line.Bot.Client: data MulticastMessageBody
- Line.Bot.Client: data Profile
- Line.Bot.Client: data PushMessageBody
- Line.Bot.Client: data QuickReply
- Line.Bot.Client: data QuickReplyButton
- Line.Bot.Client: data ReplyMessageBody
- Line.Bot.Client: instance Data.String.IsString Line.Bot.Client.ChannelToken
- Line.Bot.Client: instance GHC.Classes.Eq Line.Bot.Client.ChannelToken
- Line.Bot.Client: instance Web.Internal.HttpApiData.ToHttpApiData Line.Bot.Client.ChannelToken
- Line.Bot.Client: newtype ChannelToken
- Line.Bot.Client: newtype ReplyToken
- Line.Bot.Client: newtype URL
- Line.Bot.Webhook: AccountLink :: Text -> AccountLinkResult -> AccountLink
- Line.Bot.Webhook: Audio :: Text -> Int -> ContentProvider -> Message
- Line.Bot.Webhook: Banner :: BeaconEvent
- Line.Bot.Webhook: Beacon :: Text -> BeaconEvent -> Maybe Text -> Beacon
- Line.Bot.Webhook: ChannelSecret :: ByteString -> ChannelSecret
- Line.Bot.Webhook: Enter :: BeaconEvent
- Line.Bot.Webhook: EpochMilli :: UTCTime -> EpochMilli
- Line.Bot.Webhook: EventAccountLink :: ReplyToken -> Source -> EpochMilli -> AccountLink -> Event
- Line.Bot.Webhook: EventBeacon :: ReplyToken -> Source -> EpochMilli -> Beacon -> Event
- Line.Bot.Webhook: EventFollow :: ReplyToken -> Source -> EpochMilli -> Event
- Line.Bot.Webhook: EventJoin :: ReplyToken -> Source -> EpochMilli -> Event
- Line.Bot.Webhook: EventLeave :: Source -> EpochMilli -> Event
- Line.Bot.Webhook: EventMemberJoined :: ReplyToken -> Source -> EpochMilli -> Members -> Event
- Line.Bot.Webhook: EventMemberLeft :: Source -> EpochMilli -> Members -> Event
- Line.Bot.Webhook: EventMessage :: ReplyToken -> Message -> Source -> EpochMilli -> Event
- Line.Bot.Webhook: EventPostback :: ReplyToken -> Source -> EpochMilli -> Postback -> Event
- Line.Bot.Webhook: EventThings :: ReplyToken -> Source -> EpochMilli -> Things -> Event
- Line.Bot.Webhook: EventUnfollow :: Source -> EpochMilli -> Event
- Line.Bot.Webhook: Events :: Id User -> [Event] -> Events
- Line.Bot.Webhook: Failed :: AccountLinkResult
- Line.Bot.Webhook: File :: Text -> Int -> Text -> Message
- Line.Bot.Webhook: Image :: Text -> ContentProvider -> Message
- Line.Bot.Webhook: Leave :: BeaconEvent
- Line.Bot.Webhook: Link :: ThingsEvent
- Line.Bot.Webhook: Location :: Text -> Text -> Text -> Double -> Double -> Message
- Line.Bot.Webhook: Members :: [Source] -> Members
- Line.Bot.Webhook: Ok :: AccountLinkResult
- Line.Bot.Webhook: Postback :: Text -> PostbackDateTime -> Postback
- Line.Bot.Webhook: SourceGroup :: Id Group -> Maybe (Id User) -> Source
- Line.Bot.Webhook: SourceRoom :: Id Room -> Maybe (Id User) -> Source
- Line.Bot.Webhook: SourceUser :: Id User -> Source
- Line.Bot.Webhook: Sticker :: Text -> Text -> Text -> Message
- Line.Bot.Webhook: Text :: Text -> Text -> Message
- Line.Bot.Webhook: Things :: Text -> ThingsEvent -> Things
- Line.Bot.Webhook: Unlink :: ThingsEvent
- Line.Bot.Webhook: Video :: Text -> Int -> ContentProvider -> Message
- Line.Bot.Webhook: [$sel:address:Text] :: Message -> Text
- Line.Bot.Webhook: [$sel:beacon:EventMessage] :: Event -> Beacon
- Line.Bot.Webhook: [$sel:contentProvider:Text] :: Message -> ContentProvider
- Line.Bot.Webhook: [$sel:destination:Events] :: Events -> Id User
- Line.Bot.Webhook: [$sel:deviceId:Things] :: Things -> Text
- Line.Bot.Webhook: [$sel:dm:Beacon] :: Beacon -> Maybe Text
- Line.Bot.Webhook: [$sel:duration:Text] :: Message -> Int
- Line.Bot.Webhook: [$sel:eventType:Beacon] :: Beacon -> BeaconEvent
- Line.Bot.Webhook: [$sel:eventType:Things] :: Things -> ThingsEvent
- Line.Bot.Webhook: [$sel:events:Events] :: Events -> [Event]
- Line.Bot.Webhook: [$sel:fileName:Text] :: Message -> Text
- Line.Bot.Webhook: [$sel:fileSize:Text] :: Message -> Int
- Line.Bot.Webhook: [$sel:fromEpochMilli:EpochMilli] :: EpochMilli -> UTCTime
- Line.Bot.Webhook: [$sel:hwid:Beacon] :: Beacon -> Text
- Line.Bot.Webhook: [$sel:joined:EventMessage] :: Event -> Members
- Line.Bot.Webhook: [$sel:latitude:Text] :: Message -> Double
- Line.Bot.Webhook: [$sel:left:EventMessage] :: Event -> Members
- Line.Bot.Webhook: [$sel:link:EventMessage] :: Event -> AccountLink
- Line.Bot.Webhook: [$sel:longitude:Text] :: Message -> Double
- Line.Bot.Webhook: [$sel:members:Members] :: Members -> [Source]
- Line.Bot.Webhook: [$sel:message:EventMessage] :: Event -> Message
- Line.Bot.Webhook: [$sel:messageId:Text] :: Message -> Text
- Line.Bot.Webhook: [$sel:nonce:AccountLink] :: AccountLink -> Text
- Line.Bot.Webhook: [$sel:packageId:Text] :: Message -> Text
- Line.Bot.Webhook: [$sel:postback:EventMessage] :: Event -> Postback
- Line.Bot.Webhook: [$sel:replyToken:EventMessage] :: Event -> ReplyToken
- Line.Bot.Webhook: [$sel:result:AccountLink] :: AccountLink -> AccountLinkResult
- Line.Bot.Webhook: [$sel:source:EventMessage] :: Event -> Source
- Line.Bot.Webhook: [$sel:stickerId:Text] :: Message -> Text
- Line.Bot.Webhook: [$sel:text:Text] :: Message -> Text
- Line.Bot.Webhook: [$sel:things:EventMessage] :: Event -> Things
- Line.Bot.Webhook: [$sel:timestamp:EventMessage] :: Event -> EpochMilli
- Line.Bot.Webhook: [$sel:title:Text] :: Message -> Text
- Line.Bot.Webhook: [$sel:unChannelSecret:ChannelSecret] :: ChannelSecret -> ByteString
- Line.Bot.Webhook: data AccountLink
- Line.Bot.Webhook: data AccountLinkResult
- Line.Bot.Webhook: data Beacon
- Line.Bot.Webhook: data BeaconEvent
- Line.Bot.Webhook: data Event
- Line.Bot.Webhook: data Events
- Line.Bot.Webhook: data Members
- Line.Bot.Webhook: data Message
- Line.Bot.Webhook: data Postback
- Line.Bot.Webhook: data Source
- Line.Bot.Webhook: data Things
- Line.Bot.Webhook: data ThingsEvent
- Line.Bot.Webhook: instance (Servant.API.ContentTypes.AllCTUnrender list a, Servant.Server.Internal.HasServer api context, Servant.Server.Internal.Context.HasContextEntry context Line.Bot.Webhook.Types.ChannelSecret) => Servant.Server.Internal.HasServer (Line.Bot.Webhook.LineReqBody list a Servant.API.Sub.:> api) context
- Line.Bot.Webhook: newtype ChannelSecret
- Line.Bot.Webhook: newtype EpochMilli
+ Line.Bot.Client: getContent :: String -> Line ByteString
+ Line.Bot.Client: issueLinkToken :: Id User -> Line LinkToken
+ Line.Bot.Client: runLineWith :: (ClientM a -> IO (Either ServantError a)) -> Line a -> ChannelToken -> IO (Either ServantError a)
+ Line.Bot.Types: Action :: Maybe URL -> Action -> QuickReplyButton
+ Line.Bot.Types: ActionCamera :: Text -> Action
+ Line.Bot.Types: ActionCameraRoll :: Text -> Action
+ Line.Bot.Types: ActionLocation :: Text -> Action
+ Line.Bot.Types: ActionMessage :: Text -> Text -> Action
+ Line.Bot.Types: ActionPostback :: Text -> Text -> Text -> Action
+ Line.Bot.Types: ActionURI :: Text -> Text -> Action
+ Line.Bot.Types: Audio :: URL -> Int -> Maybe QuickReply -> Message
+ Line.Bot.Types: ChannelSecret :: ByteString -> ChannelSecret
+ Line.Bot.Types: ChannelToken :: Text -> ChannelToken
+ Line.Bot.Types: Group :: ChatType
+ Line.Bot.Types: Image :: URL -> URL -> Maybe QuickReply -> Message
+ Line.Bot.Types: LinkToken :: Text -> LinkToken
+ Line.Bot.Types: Location :: Text -> Text -> Double -> Double -> Maybe QuickReply -> Message
+ Line.Bot.Types: MulticastMessageBody :: [Id User] -> [Message] -> MulticastMessageBody
+ Line.Bot.Types: Profile :: Text -> Id User -> URL -> Maybe Text -> Profile
+ Line.Bot.Types: PushMessageBody :: Id a -> [Message] -> PushMessageBody
+ Line.Bot.Types: QuickReply :: [QuickReplyButton] -> QuickReply
+ Line.Bot.Types: ReplyMessageBody :: ReplyToken -> [Message] -> ReplyMessageBody
+ Line.Bot.Types: ReplyToken :: Text -> ReplyToken
+ Line.Bot.Types: Room :: ChatType
+ Line.Bot.Types: Sticker :: Text -> Text -> Maybe QuickReply -> Message
+ Line.Bot.Types: Text :: Text -> Maybe QuickReply -> Message
+ Line.Bot.Types: URL :: Text -> URL
+ Line.Bot.Types: User :: ChatType
+ Line.Bot.Types: Video :: URL -> URL -> Maybe QuickReply -> Message
+ Line.Bot.Types: [$sel:action:Action] :: QuickReplyButton -> Action
+ Line.Bot.Types: [$sel:address:Text] :: Message -> Text
+ Line.Bot.Types: [$sel:displayName:Profile] :: Profile -> Text
+ Line.Bot.Types: [$sel:displayText:ActionPostback] :: Action -> Text
+ Line.Bot.Types: [$sel:duration:Text] :: Message -> Int
+ Line.Bot.Types: [$sel:imageUrl:Action] :: QuickReplyButton -> Maybe URL
+ Line.Bot.Types: [$sel:items:QuickReply] :: QuickReply -> [QuickReplyButton]
+ Line.Bot.Types: [$sel:label:ActionPostback] :: Action -> Text
+ Line.Bot.Types: [$sel:latitude:Text] :: Message -> Double
+ Line.Bot.Types: [$sel:linkToken:LinkToken] :: LinkToken -> Text
+ Line.Bot.Types: [$sel:longitude:Text] :: Message -> Double
+ Line.Bot.Types: [$sel:originalContentUrl:Text] :: Message -> URL
+ Line.Bot.Types: [$sel:packageId:Text] :: Message -> Text
+ Line.Bot.Types: [$sel:pictureUrl:Profile] :: Profile -> URL
+ Line.Bot.Types: [$sel:postbackData:ActionPostback] :: Action -> Text
+ Line.Bot.Types: [$sel:previewImageUrl:Text] :: Message -> URL
+ Line.Bot.Types: [$sel:quickReply:Text] :: Message -> Maybe QuickReply
+ Line.Bot.Types: [$sel:statusMessage:Profile] :: Profile -> Maybe Text
+ Line.Bot.Types: [$sel:stickerId:Text] :: Message -> Text
+ Line.Bot.Types: [$sel:text:ActionPostback] :: Action -> Text
+ Line.Bot.Types: [$sel:text:Text] :: Message -> Text
+ Line.Bot.Types: [$sel:title:Text] :: Message -> Text
+ Line.Bot.Types: [$sel:unChannelSecret:ChannelSecret] :: ChannelSecret -> ByteString
+ Line.Bot.Types: [$sel:uri:ActionPostback] :: Action -> Text
+ Line.Bot.Types: [$sel:userId:Profile] :: Profile -> Id User
+ Line.Bot.Types: [GroupId] :: Text -> Id Group
+ Line.Bot.Types: [RoomId] :: Text -> Id Room
+ Line.Bot.Types: [UserId] :: Text -> Id User
+ Line.Bot.Types: data Action
+ Line.Bot.Types: data ChatType
+ Line.Bot.Types: data Id :: ChatType -> *
+ Line.Bot.Types: data LinkToken
+ Line.Bot.Types: data Message
+ Line.Bot.Types: data MulticastMessageBody
+ Line.Bot.Types: data Profile
+ Line.Bot.Types: data PushMessageBody
+ Line.Bot.Types: data QuickReply
+ Line.Bot.Types: data QuickReplyButton
+ Line.Bot.Types: data ReplyMessageBody
+ Line.Bot.Types: instance Data.Aeson.Types.FromJSON.FromJSON (Line.Bot.Types.Id 'Line.Bot.Types.Group)
+ Line.Bot.Types: instance Data.Aeson.Types.FromJSON.FromJSON (Line.Bot.Types.Id 'Line.Bot.Types.Room)
+ Line.Bot.Types: instance Data.Aeson.Types.FromJSON.FromJSON (Line.Bot.Types.Id 'Line.Bot.Types.User)
+ Line.Bot.Types: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Types.LinkToken
+ Line.Bot.Types: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Types.Profile
+ Line.Bot.Types: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Types.ReplyToken
+ Line.Bot.Types: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Types.URL
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON (Line.Bot.Types.Id a)
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.Action
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.Message
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.MulticastMessageBody
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.PushMessageBody
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.QuickReply
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.QuickReplyButton
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.ReplyMessageBody
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.ReplyToken
+ Line.Bot.Types: instance Data.Aeson.Types.ToJSON.ToJSON Line.Bot.Types.URL
+ Line.Bot.Types: instance Data.String.IsString Line.Bot.Types.ChannelSecret
+ Line.Bot.Types: instance Data.String.IsString Line.Bot.Types.ChannelToken
+ Line.Bot.Types: instance GHC.Classes.Eq (Line.Bot.Types.Id a)
+ Line.Bot.Types: instance GHC.Classes.Eq Line.Bot.Types.Action
+ Line.Bot.Types: instance GHC.Classes.Eq Line.Bot.Types.ChannelToken
+ Line.Bot.Types: instance GHC.Classes.Eq Line.Bot.Types.LinkToken
+ Line.Bot.Types: instance GHC.Classes.Eq Line.Bot.Types.Message
+ Line.Bot.Types: instance GHC.Classes.Eq Line.Bot.Types.QuickReply
+ Line.Bot.Types: instance GHC.Classes.Eq Line.Bot.Types.QuickReplyButton
+ Line.Bot.Types: instance GHC.Classes.Eq Line.Bot.Types.ReplyToken
+ Line.Bot.Types: instance GHC.Classes.Eq Line.Bot.Types.URL
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.Action
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.LinkToken
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.Message
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.MulticastMessageBody
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.Profile
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.QuickReply
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.QuickReplyButton
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.ReplyMessageBody
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.ReplyToken
+ Line.Bot.Types: instance GHC.Generics.Generic Line.Bot.Types.URL
+ Line.Bot.Types: instance GHC.Show.Show (Line.Bot.Types.Id a)
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.Action
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.LinkToken
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.Message
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.MulticastMessageBody
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.Profile
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.PushMessageBody
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.QuickReply
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.QuickReplyButton
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.ReplyMessageBody
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.ReplyToken
+ Line.Bot.Types: instance GHC.Show.Show Line.Bot.Types.URL
+ Line.Bot.Types: instance Web.Internal.HttpApiData.ToHttpApiData (Line.Bot.Types.Id a)
+ Line.Bot.Types: instance Web.Internal.HttpApiData.ToHttpApiData Line.Bot.Types.ChannelToken
+ Line.Bot.Types: newtype ChannelSecret
+ Line.Bot.Types: newtype ChannelToken
+ Line.Bot.Types: newtype ReplyToken
+ Line.Bot.Types: newtype URL
+ Line.Bot.Webhook: instance (Servant.API.ContentTypes.AllCTUnrender list a, Servant.Server.Internal.HasServer api context, Servant.Server.Internal.Context.HasContextEntry context Line.Bot.Types.ChannelSecret) => Servant.Server.Internal.HasServer (Line.Bot.Webhook.LineReqBody list a Servant.API.Sub.:> api) context
+ Line.Bot.Webhook.Events: AccountLink :: Text -> AccountLinkResult -> AccountLink
+ Line.Bot.Webhook.Events: Audio :: Text -> Int -> ContentProvider -> Message
+ Line.Bot.Webhook.Events: Banner :: BeaconEvent
+ Line.Bot.Webhook.Events: Beacon :: Text -> BeaconEvent -> Maybe Text -> Beacon
+ Line.Bot.Webhook.Events: Enter :: BeaconEvent
+ Line.Bot.Webhook.Events: EpochMilli :: UTCTime -> EpochMilli
+ Line.Bot.Webhook.Events: EventAccountLink :: ReplyToken -> Source -> EpochMilli -> AccountLink -> Event
+ Line.Bot.Webhook.Events: EventBeacon :: ReplyToken -> Source -> EpochMilli -> Beacon -> Event
+ Line.Bot.Webhook.Events: EventFollow :: ReplyToken -> Source -> EpochMilli -> Event
+ Line.Bot.Webhook.Events: EventJoin :: ReplyToken -> Source -> EpochMilli -> Event
+ Line.Bot.Webhook.Events: EventLeave :: Source -> EpochMilli -> Event
+ Line.Bot.Webhook.Events: EventMemberJoined :: ReplyToken -> Source -> EpochMilli -> Members -> Event
+ Line.Bot.Webhook.Events: EventMemberLeft :: Source -> EpochMilli -> Members -> Event
+ Line.Bot.Webhook.Events: EventMessage :: ReplyToken -> Message -> Source -> EpochMilli -> Event
+ Line.Bot.Webhook.Events: EventPostback :: ReplyToken -> Source -> EpochMilli -> Postback -> Event
+ Line.Bot.Webhook.Events: EventThings :: ReplyToken -> Source -> EpochMilli -> Things -> Event
+ Line.Bot.Webhook.Events: EventUnfollow :: Source -> EpochMilli -> Event
+ Line.Bot.Webhook.Events: Events :: Id User -> [Event] -> Events
+ Line.Bot.Webhook.Events: Failed :: AccountLinkResult
+ Line.Bot.Webhook.Events: File :: Text -> Int -> Text -> Message
+ Line.Bot.Webhook.Events: Image :: Text -> ContentProvider -> Message
+ Line.Bot.Webhook.Events: Leave :: BeaconEvent
+ Line.Bot.Webhook.Events: Link :: ThingsEvent
+ Line.Bot.Webhook.Events: Location :: Text -> Text -> Text -> Double -> Double -> Message
+ Line.Bot.Webhook.Events: Members :: [Source] -> Members
+ Line.Bot.Webhook.Events: Ok :: AccountLinkResult
+ Line.Bot.Webhook.Events: Postback :: Text -> PostbackDateTime -> Postback
+ Line.Bot.Webhook.Events: SourceGroup :: Id Group -> Maybe (Id User) -> Source
+ Line.Bot.Webhook.Events: SourceRoom :: Id Room -> Maybe (Id User) -> Source
+ Line.Bot.Webhook.Events: SourceUser :: Id User -> Source
+ Line.Bot.Webhook.Events: Sticker :: Text -> Text -> Text -> Message
+ Line.Bot.Webhook.Events: Text :: Text -> Text -> Message
+ Line.Bot.Webhook.Events: Things :: Text -> ThingsEvent -> Things
+ Line.Bot.Webhook.Events: Unlink :: ThingsEvent
+ Line.Bot.Webhook.Events: Video :: Text -> Int -> ContentProvider -> Message
+ Line.Bot.Webhook.Events: [$sel:address:Text] :: Message -> Text
+ Line.Bot.Webhook.Events: [$sel:beacon:EventMessage] :: Event -> Beacon
+ Line.Bot.Webhook.Events: [$sel:contentProvider:Text] :: Message -> ContentProvider
+ Line.Bot.Webhook.Events: [$sel:destination:Events] :: Events -> Id User
+ Line.Bot.Webhook.Events: [$sel:deviceId:Things] :: Things -> Text
+ Line.Bot.Webhook.Events: [$sel:dm:Beacon] :: Beacon -> Maybe Text
+ Line.Bot.Webhook.Events: [$sel:duration:Text] :: Message -> Int
+ Line.Bot.Webhook.Events: [$sel:eventType:Beacon] :: Beacon -> BeaconEvent
+ Line.Bot.Webhook.Events: [$sel:eventType:Things] :: Things -> ThingsEvent
+ Line.Bot.Webhook.Events: [$sel:events:Events] :: Events -> [Event]
+ Line.Bot.Webhook.Events: [$sel:fileName:Text] :: Message -> Text
+ Line.Bot.Webhook.Events: [$sel:fileSize:Text] :: Message -> Int
+ Line.Bot.Webhook.Events: [$sel:fromEpochMilli:EpochMilli] :: EpochMilli -> UTCTime
+ Line.Bot.Webhook.Events: [$sel:hwid:Beacon] :: Beacon -> Text
+ Line.Bot.Webhook.Events: [$sel:joined:EventMessage] :: Event -> Members
+ Line.Bot.Webhook.Events: [$sel:latitude:Text] :: Message -> Double
+ Line.Bot.Webhook.Events: [$sel:left:EventMessage] :: Event -> Members
+ Line.Bot.Webhook.Events: [$sel:link:EventMessage] :: Event -> AccountLink
+ Line.Bot.Webhook.Events: [$sel:longitude:Text] :: Message -> Double
+ Line.Bot.Webhook.Events: [$sel:members:Members] :: Members -> [Source]
+ Line.Bot.Webhook.Events: [$sel:message:EventMessage] :: Event -> Message
+ Line.Bot.Webhook.Events: [$sel:messageId:Text] :: Message -> Text
+ Line.Bot.Webhook.Events: [$sel:nonce:AccountLink] :: AccountLink -> Text
+ Line.Bot.Webhook.Events: [$sel:packageId:Text] :: Message -> Text
+ Line.Bot.Webhook.Events: [$sel:postback:EventMessage] :: Event -> Postback
+ Line.Bot.Webhook.Events: [$sel:replyToken:EventMessage] :: Event -> ReplyToken
+ Line.Bot.Webhook.Events: [$sel:result:AccountLink] :: AccountLink -> AccountLinkResult
+ Line.Bot.Webhook.Events: [$sel:source:EventMessage] :: Event -> Source
+ Line.Bot.Webhook.Events: [$sel:stickerId:Text] :: Message -> Text
+ Line.Bot.Webhook.Events: [$sel:text:Text] :: Message -> Text
+ Line.Bot.Webhook.Events: [$sel:things:EventMessage] :: Event -> Things
+ Line.Bot.Webhook.Events: [$sel:timestamp:EventMessage] :: Event -> EpochMilli
+ Line.Bot.Webhook.Events: [$sel:title:Text] :: Message -> Text
+ Line.Bot.Webhook.Events: data AccountLink
+ Line.Bot.Webhook.Events: data AccountLinkResult
+ Line.Bot.Webhook.Events: data Beacon
+ Line.Bot.Webhook.Events: data BeaconEvent
+ Line.Bot.Webhook.Events: data Event
+ Line.Bot.Webhook.Events: data Events
+ Line.Bot.Webhook.Events: data Members
+ Line.Bot.Webhook.Events: data Message
+ Line.Bot.Webhook.Events: data Postback
+ Line.Bot.Webhook.Events: data Source
+ Line.Bot.Webhook.Events: data Things
+ Line.Bot.Webhook.Events: data ThingsEvent
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.AccountLink
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.AccountLinkResult
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.Beacon
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.BeaconEvent
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.ContentProvider
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.EpochMilli
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.Event
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.Events
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.Members
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.Message
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.Postback
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.PostbackDateTime
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.Source
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.Things
+ Line.Bot.Webhook.Events: instance Data.Aeson.Types.FromJSON.FromJSON Line.Bot.Webhook.Events.ThingsEvent
+ Line.Bot.Webhook.Events: instance Data.Time.Format.FormatTime Line.Bot.Webhook.Events.EpochMilli
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.AccountLink
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.AccountLinkResult
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.Beacon
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.BeaconEvent
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.ContentProvider
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.EpochMilli
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.Event
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.Events
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.Members
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.Message
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.Postback
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.PostbackDateTime
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.Source
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.Things
+ Line.Bot.Webhook.Events: instance GHC.Classes.Eq Line.Bot.Webhook.Events.ThingsEvent
+ Line.Bot.Webhook.Events: instance GHC.Classes.Ord Line.Bot.Webhook.Events.BeaconEvent
+ Line.Bot.Webhook.Events: instance GHC.Classes.Ord Line.Bot.Webhook.Events.EpochMilli
+ Line.Bot.Webhook.Events: instance GHC.Classes.Ord Line.Bot.Webhook.Events.ThingsEvent
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.AccountLink
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.AccountLinkResult
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.Beacon
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.BeaconEvent
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.ContentProvider
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.Event
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.Events
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.Members
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.Message
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.Things
+ Line.Bot.Webhook.Events: instance GHC.Generics.Generic Line.Bot.Webhook.Events.ThingsEvent
+ Line.Bot.Webhook.Events: instance GHC.Read.Read Line.Bot.Webhook.Events.BeaconEvent
+ Line.Bot.Webhook.Events: instance GHC.Read.Read Line.Bot.Webhook.Events.EpochMilli
+ Line.Bot.Webhook.Events: instance GHC.Read.Read Line.Bot.Webhook.Events.ThingsEvent
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.AccountLink
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.AccountLinkResult
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.Beacon
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.BeaconEvent
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.ContentProvider
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.EpochMilli
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.Event
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.Events
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.Members
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.Message
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.Postback
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.PostbackDateTime
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.Source
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.Things
+ Line.Bot.Webhook.Events: instance GHC.Show.Show Line.Bot.Webhook.Events.ThingsEvent
+ Line.Bot.Webhook.Events: newtype EpochMilli
- Line.Bot.Client: runLine :: ChannelToken -> Line a -> IO (Either ServantError a)
+ Line.Bot.Client: runLine :: Line a -> ChannelToken -> IO (Either ServantError a)

Files

LICENSE view
@@ -1,4 +1,4 @@-Copyright Author name here (c) 2018+Copyright Alexandre Moreno (c) 2018  All rights reserved. 
examples/Echo.hs view
@@ -10,7 +10,9 @@ import           Control.Monad.IO.Class               (liftIO) import           Control.Monad.Trans.Reader           (ReaderT, ask, runReaderT) import           Data.String                          (fromString)-import           Line.Bot.Client                      as B+import           Line.Bot.Client                      (Line, replyMessage,+                                                       runLine)+import           Line.Bot.Types                       as B import           Line.Bot.Webhook                     as W import           Network.Wai.Handler.Warp             (run) import           Network.Wai.Middleware.RequestLogger (logStdout)@@ -27,14 +29,14 @@   replyMessage replyToken [B.Text text Nothing] echo _ = return NoContent -handleEvents :: Events -> WebM NoContent-handleEvents Events { events } = do+handleEvents :: [Event] -> WebM NoContent+handleEvents events = do   token <- ask-  _     <- liftIO $ mapM_ (runLine token . echo) events+  _     <- liftIO $ mapM_ (flip runLine token . echo) events   return NoContent  echoServer :: ServerT API WebM-echoServer = handleEvents+echoServer = handleEvents . events  app :: ChannelToken -> ChannelSecret -> Application app token secret = serveWithContext api context server
line-bot-sdk.cabal view
@@ -1,5 +1,5 @@ name:                line-bot-sdk-version:             0.1.0.0+version:             0.2.0.0 synopsis:            Haskell SDK for LINE Messaging API homepage:            https://github.com/moleike/line-bot-sdk#readme bug-reports:         https://github.com/moleike/line-bot-sdk/issues@@ -28,11 +28,11 @@ library   hs-source-dirs:      src   exposed-modules:     Line.Bot.Webhook+                     , Line.Bot.Webhook.Events                      , Line.Bot.Client+                     , Line.Bot.Types    other-modules:       Line.Bot.Endpoints-                     , Line.Bot.Types-                     , Line.Bot.Webhook.Types    build-depends:       base                 >= 4.7 && < 5                      , aeson                >= 1.4.2 && < 1.5
src/Line/Bot/Client.hs view
@@ -7,20 +7,32 @@ {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-} {-# LANGUAGE UndecidableInstances  #-}+-- |+-- Module      : Line.Bot.Client+-- Copyright   : (c) Alexandre Moreno, 2019+-- License     : BSD3+-- Maintainer  : alexmorenocano@gmail.com+-- Stability   : experimental  module Line.Bot.Client-  ( module Line.Bot.Types+  ( Line   , runLine-  , Line-  , ChannelToken(..)+  , runLineWith+  -- ** Profile   , getProfile+  -- ** Group   , getGroupMemberProfile   , leaveGroup+  -- ** Room   , getRoomMemberProfile   , leaveRoom+  -- ** Message   , replyMessage   , pushMessage   , multicastMessage+  , getContent+  -- ** Account Link+  , issueLinkToken   ) where @@ -49,29 +61,31 @@ host :: BaseUrl host = BaseUrl Https "api.line.me" 443 "" -newtype ChannelToken = ChannelToken Text-  deriving (Eq)--instance IsString ChannelToken where-  fromString s = ChannelToken (fromString s)--instance ToHttpApiData ChannelToken where-  toQueryParam (ChannelToken t) = "Bearer " <> t-+-- | @Line@ is the monad in which bot requests run. Contains the+-- OAuth access token for a channel type Line = ReaderT ChannelToken ClientM  type Auth = AuthenticatedRequest (AuthProtect ChannelAuth)  type instance AuthClientData (AuthProtect ChannelAuth) = ChannelToken -runLine' :: ClientM a -> IO (Either ServantError a)-runLine' comp = do+defaultClient:: ClientM a -> IO (Either ServantError a)+defaultClient comp = do   manager <- newManager tlsManagerSettings   runClientM comp (mkClientEnv manager host) -runLine :: ChannelToken -> Line a -> IO (Either ServantError a)-runLine token comp = runLine' $ runReaderT comp token+-- | Runs a @Line@ computation with the given channel access token+runLine :: Line a -> ChannelToken -> IO (Either ServantError a)+runLine = runLineWith defaultClient +-- | Runs the monad with a different client evironment+runLineWith+  :: (ClientM a -> IO (Either ServantError a))+  -> Line a+  -> ChannelToken+  -> IO (Either ServantError a)+runLineWith f comp token = f $ runReaderT comp token+ mkAuth :: ChannelToken -> Auth mkAuth token = mkAuthenticatedRequest token addAuthHeader  where@@ -96,6 +110,8 @@  getContent' :: Auth -> String -> ClientM ByteString +issueLinkToken' :: Auth -> Id User -> ClientM LinkToken+ getProfile'   :<|> getGroupMemberProfile'   :<|> leaveGroup'@@ -104,7 +120,8 @@   :<|> replyMessage'   :<|> pushMessage'   :<|> multicastMessage'-  :<|> getContent' = client (Proxy :: Proxy Endpoints)+  :<|> getContent'+  :<|> issueLinkToken' = client (Proxy :: Proxy Endpoints)  getProfile :: Id User -> Line Profile getProfile a = ask >>= \token -> lift $ getProfile' (mkAuth token) a@@ -135,3 +152,10 @@ multicastMessage a ms = ask   >>= \token -> lift $ multicastMessage' (mkAuth token) body   where body = MulticastMessageBody a ms++getContent :: String -> Line ByteString+getContent a = ask >>= \token -> lift $ getContent' (mkAuth token) a++issueLinkToken :: Id User -> Line LinkToken+issueLinkToken a = ask >>= \token -> lift $ issueLinkToken' (mkAuth token) a+
src/Line/Bot/Endpoints.hs view
@@ -7,6 +7,12 @@ {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-} {-# LANGUAGE UndecidableInstances  #-}+-- |+-- Module      : Line.Bot.Endpoints+-- Copyright   : (c) Alexandre Moreno, 2019+-- License     : BSD3+-- Maintainer  : alexmorenocano@gmail.com+-- Stability   : experimental  module Line.Bot.Endpoints where @@ -72,6 +78,12 @@   :> "content"   :> Get '[OctetStream] ByteString +type IssueLinkToken = AuthProtect ChannelAuth+  :> "user"+  :> Capture "userId" (Id User)+  :> "linkToken"+  :> Get '[JSON] LinkToken+ type Endpoints = "v2" :> "bot" :>   (    GetProfile   :<|> GetGroupMemberProfile@@ -82,4 +94,5 @@   :<|> PushMessage   :<|> MulticastMessage   :<|> GetContent+  :<|> IssueLinkToken   )
src/Line/Bot/Types.hs view
@@ -11,13 +11,22 @@ {-# LANGUAGE OverloadedStrings         #-} {-# LANGUAGE RecordWildCards           #-} {-# LANGUAGE StandaloneDeriving        #-}+-- |+-- Module      : Line.Bot.Types+-- Copyright   : (c) Alexandre Moreno, 2019+-- License     : BSD3+-- Maintainer  : alexmorenocano@gmail.com+-- Stability   : experimental  module Line.Bot.Types-  ( ChatType(..)+  ( ChannelToken(..)+  , ChannelSecret(..)+  , ChatType(..)   , Id(..)   , URL(..)   , Message(..)   , ReplyToken(..)+  , LinkToken(..)   , ReplyMessageBody(ReplyMessageBody)   , PushMessageBody(PushMessageBody)   , MulticastMessageBody(MulticastMessageBody)@@ -30,17 +39,34 @@  import           Data.Aeson import           Data.Aeson.Types-import           Data.Char        (toLower)-import           Data.List        as L (stripPrefix)-import           Data.Maybe       (fromJust)+import qualified Data.ByteString.Char8 as B+import           Data.Char             (toLower)+import           Data.List             as L (stripPrefix)+import           Data.Maybe            (fromJust) import           Data.String-import           Data.Text        as T hiding (drop, toLower)-import           GHC.Generics     hiding (to)+import           Data.Text             as T hiding (drop, toLower)+import           GHC.Generics          hiding (to) import           Servant.API import           Text.Show +newtype ChannelToken = ChannelToken Text+  deriving (Eq)++instance IsString ChannelToken where+  fromString s = ChannelToken (fromString s)++instance ToHttpApiData ChannelToken where+  toQueryParam (ChannelToken t) = "Bearer " <> t++newtype ChannelSecret = ChannelSecret+  { unChannelSecret :: B.ByteString }++instance IsString ChannelSecret where+  fromString s = ChannelSecret (B.pack s)+ data ChatType = User | Group | Room +-- | ID of a chat user, group or room data Id :: ChatType -> * where   UserId  :: Text -> Id User   GroupId :: Text -> Id Group@@ -129,6 +155,11 @@  instance ToJSON ReplyToken instance FromJSON ReplyToken++data LinkToken = LinkToken { linkToken :: Text }+  deriving (Eq, Show, Generic)++instance FromJSON LinkToken  data ReplyMessageBody = ReplyMessageBody   { replyToken :: ReplyToken
src/Line/Bot/Webhook.hs view
@@ -12,14 +12,19 @@ {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-} {-# LANGUAGE UndecidableInstances  #-}-+-- |+-- Module      : Line.Bot.Webhook+-- Copyright   : (c) Alexandre Moreno, 2019+-- License     : BSD3+-- Maintainer  : alexmorenocano@gmail.com+-- Stability   : experimental  module Line.Bot.Webhook-  ( module Line.Bot.Webhook.Types-  , Webhook+  ( Webhook   , LineReqBody+  , module Events   )-  where+where  import           Control.Monad.IO.Class   (liftIO) import qualified Crypto.Hash.SHA256       as SHA256@@ -32,7 +37,8 @@ import           Data.Proxy import           Data.String.Conversions  (cs) import           Data.Typeable            (Typeable)-import           Line.Bot.Webhook.Types+import           Line.Bot.Types           (ChannelSecret (..))+import           Line.Bot.Webhook.Events  as Events import           Network.HTTP.Types       (HeaderName, hContentType) import           Network.Wai              (Request, lazyRequestBody,                                            requestHeaders)
+ src/Line/Bot/Webhook/Events.hs view
@@ -0,0 +1,299 @@+{-# LANGUAGE DataKinds                  #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DuplicateRecordFields      #-}+{-# LANGUAGE ExistentialQuantification  #-}+{-# LANGUAGE ExtendedDefaultRules       #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE RecordWildCards            #-}+{-# LANGUAGE StandaloneDeriving         #-}+-- |+-- Module      : Line.Bot.Webhook.Events+-- Copyright   : (c) Alexandre Moreno, 2019+-- License     : BSD3+-- Maintainer  : alexmorenocano@gmail.com+-- Stability   : experimental++module Line.Bot.Webhook.Events+  ( Events(..)+  , Event(..)+  , Message(..)+  , EpochMilli(..)+  , Source(..)+  , Members(..)+  , Postback(..)+  , Beacon(..)+  , BeaconEvent(..)+  , Things(..)+  , ThingsEvent(..)+  , AccountLink(..)+  , AccountLinkResult(..)+  )+where++import           Data.Aeson+import           Data.Aeson.Types+import           Data.Char+import           Data.Foldable+import           Data.List             as L (stripPrefix)+import           Data.Maybe+import           Data.Scientific+import           Data.String+import           Data.Text             as T hiding (drop, stripPrefix, toLower)+import           Data.Time             (LocalTime, UTCTime)+import           Data.Time.Calendar    (Day)+import           Data.Time.Clock.POSIX+import           Data.Time.Format+import           Data.Time.LocalTime+import           Data.Typeable         (Typeable)+import           GHC.Generics          (Generic)+import           Line.Bot.Types        hiding (Message, Text)+++data Events = Events+  { destination :: Id User+  , events      :: [Event]+  }+  deriving (Eq, Show, Generic)++instance FromJSON Events++data Event =+    EventMessage      { replyToken :: ReplyToken+                      , message    :: Message+                      , source     :: Source+                      , timestamp  :: EpochMilli+                      }+  | EventFollow       { replyToken :: ReplyToken+                      , source     :: Source+                      , timestamp  :: EpochMilli+                      }+  | EventUnfollow     { source    :: Source+                      , timestamp :: EpochMilli+                      }+  | EventJoin         { replyToken :: ReplyToken+                      , source     :: Source+                      , timestamp  :: EpochMilli+                      }+  | EventLeave        { source    :: Source+                      , timestamp :: EpochMilli+                      }+  | EventMemberJoined { replyToken :: ReplyToken+                      , source     :: Source+                      , timestamp  :: EpochMilli+                      , joined     :: Members+                      }+  | EventMemberLeft   { source    :: Source+                      , timestamp :: EpochMilli+                      , left      :: Members+                      }+  | EventPostback     { replyToken :: ReplyToken+                      , source     :: Source+                      , timestamp  :: EpochMilli+                      , postback   :: Postback+                      }+  | EventBeacon       { replyToken :: ReplyToken+                      , source     :: Source+                      , timestamp  :: EpochMilli+                      , beacon     :: Beacon+                      }+  | EventAccountLink  { replyToken :: ReplyToken+                      , source     :: Source+                      , timestamp  :: EpochMilli+                      , link       :: AccountLink+                      }+  | EventThings       { replyToken :: ReplyToken+                      , source     :: Source+                      , timestamp  :: EpochMilli+                      , things     :: Things+                      }+  deriving (Eq, Show, Generic)++instance FromJSON Event where+  parseJSON = genericParseJSON $+    defaultOptions { sumEncoding            = TaggedObject+                     { tagFieldName      = "type"+                     , contentsFieldName = undefined+                     }+                   , constructorTagModifier = (\(x : xs) -> toLower x : xs) . drop 5+                   }++data Message =+    Text     { messageId :: Text+             , text      :: Text+             }+  | Image    { messageId       :: Text+             , contentProvider :: ContentProvider+             }+  | Video    { messageId       :: Text+             , duration        :: Int+             , contentProvider :: ContentProvider+             }+  | Audio    { messageId       :: Text+             , duration        :: Int+             , contentProvider :: ContentProvider+             }+  | File     { messageId :: Text+             , fileSize  :: Int+             , fileName  :: Text+             }+  | Location { messageId :: Text+             , title     :: Text+             , address   :: Text+             , latitude  :: Double+             , longitude :: Double+             }+  | Sticker  { messageId :: Text+             , packageId :: Text+             , stickerId :: Text+             }+  deriving (Eq, Show, Generic)++messageJSONOptions :: Options+messageJSONOptions = defaultOptions+  { sumEncoding            = TaggedObject+    { tagFieldName      = "type"+    , contentsFieldName = undefined+    }+  , constructorTagModifier = fmap toLower+  , fieldLabelModifier     = \orig ->+      case L.stripPrefix "message" orig of+        Just s  -> fmap toLower s+        Nothing -> orig+  , omitNothingFields = True+  }++instance FromJSON Message where+  parseJSON = genericParseJSON messageJSONOptions+++data ContentProvider = ContentProvider+  { originalContentUrl :: Maybe URL+  , previewImageUrl    :: Maybe URL+  }+  deriving (Eq, Show, Generic)++instance FromJSON ContentProvider++newtype EpochMilli = EpochMilli {+  fromEpochMilli :: UTCTime+  -- ^ Acquire the underlying value.+} deriving (Eq, Ord, Read, Show, FormatTime)++instance FromJSON EpochMilli where+  parseJSON = withScientific "EpochMilli" $ \t ->+    pure $ millis t+    where+      millis = EpochMilli+             . posixSecondsToUTCTime+             . fromRational+             . toRational+             . (/ 1000)+++data Source =+    SourceUser (Id User)+  | SourceGroup (Id Group) (Maybe (Id User))+  | SourceRoom (Id Room) (Maybe (Id User))+  deriving (Eq, Show)++instance FromJSON Source where+  parseJSON = withObject "Source" $ \o -> do+    messageType <- o .: "type"+    case messageType of+      "user"  -> SourceUser  <$> o .: "userId"+      "group" -> SourceGroup <$> o .: "groupId" <*> o .:? "userId"+      "room"  -> SourceRoom  <$> o .: "roomId"  <*> o .:? "userId"+      _       -> fail ("unknown source: " ++ messageType)+++data Members = Members { members :: [Source] }+  deriving (Eq, Show, Generic)++instance FromJSON Members++data PostbackDateTime =+    PostbackDay Day+  | PostbackLocalTime LocalTime+  | PostbackTimeOfDay TimeOfDay+  deriving (Eq, Show)++instance FromJSON PostbackDateTime where+  parseJSON = withObject "PostbackDateTime" $ \o -> do+    dateTime <- asum+      [ PostbackDay       <$> o .: "date"+      , PostbackLocalTime <$> o .: "datetime"+      , PostbackTimeOfDay <$> o .: "time"+      ]+    return dateTime++data Postback = Postback Text PostbackDateTime+  deriving (Eq, Show)++instance FromJSON Postback where+  parseJSON = withObject "Postback" $ \o -> do+    postbackData <- o .: "data"+    params       <- o .: "params"+    return $ Postback postbackData params++data BeaconEvent = Enter | Leave | Banner+  deriving (Show, Read, Eq, Ord, Generic)++instance FromJSON BeaconEvent where+  parseJSON = genericParseJSON $+    defaultOptions { constructorTagModifier = fmap toLower+                   , allNullaryToStringTag  = True+                   }++data Beacon = Beacon+   { hwid      :: Text+   , eventType :: BeaconEvent+   , dm        :: Maybe Text+   }+   deriving (Eq, Show, Generic)++instance FromJSON Beacon where+  parseJSON = withObject "Beacon" $ \o -> do+    hwid      <- o .:  "hwid"+    eventType <- o .:  "type"+    dm        <- o .:? "dm"+    return $ Beacon{..}++data AccountLinkResult = Ok | Failed+ deriving (Eq, Show, Generic)++instance FromJSON AccountLinkResult where+  parseJSON = genericParseJSON $+    defaultOptions { constructorTagModifier = fmap toLower+                   , allNullaryToStringTag  = True+                   }++data AccountLink = AccountLink+   { nonce  :: Text+   , result :: AccountLinkResult+   }+   deriving (Eq, Show, Generic)++instance FromJSON AccountLink++data ThingsEvent = Link | Unlink+  deriving (Show, Read, Eq, Ord, Generic)++instance FromJSON ThingsEvent where+  parseJSON = genericParseJSON $+    defaultOptions { constructorTagModifier = fmap toLower+                   , allNullaryToStringTag  = True+                   }++data Things = Things+   { deviceId  :: Text+   , eventType :: ThingsEvent+   }+   deriving (Eq, Show, Generic)++instance FromJSON Things where+  parseJSON = withObject "Things" $ \o -> do+    deviceId  <- o .: "deviceId"+    eventType <- o .: "type"+    return $ Things{..}
− src/Line/Bot/Webhook/Types.hs
@@ -1,301 +0,0 @@-{-# LANGUAGE DataKinds                  #-}-{-# LANGUAGE DeriveGeneric              #-}-{-# LANGUAGE DuplicateRecordFields      #-}-{-# LANGUAGE ExistentialQuantification  #-}-{-# LANGUAGE ExtendedDefaultRules       #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings          #-}-{-# LANGUAGE RecordWildCards            #-}-{-# LANGUAGE StandaloneDeriving         #-}--module Line.Bot.Webhook.Types-  ( ChannelSecret(..)-  , Events(..)-  , Event(..)-  , Message(..)-  , EpochMilli(..)-  , Source(..)-  , Members(..)-  , Postback(..)-  , Beacon(..)-  , BeaconEvent(..)-  , Things(..)-  , ThingsEvent(..)-  , AccountLink(..)-  , AccountLinkResult(..)-  )-where--import           Data.Aeson-import           Data.Aeson.Types-import qualified Data.ByteString.Char8 as B-import           Data.Char-import           Data.Foldable-import           Data.List             as L (stripPrefix)-import           Data.Maybe-import           Data.Scientific-import           Data.String-import           Data.Text             as T hiding (drop, stripPrefix, toLower)-import           Data.Time             (LocalTime, UTCTime)-import           Data.Time.Calendar    (Day)-import           Data.Time.Clock.POSIX-import           Data.Time.Format-import           Data.Time.LocalTime-import           Data.Typeable         (Typeable)-import           GHC.Generics          (Generic)-import           Line.Bot.Types        hiding (Message, Text)---newtype ChannelSecret = ChannelSecret-  { unChannelSecret :: B.ByteString }--instance IsString ChannelSecret where-  fromString s = ChannelSecret (B.pack s)--data Events = Events-  { destination :: Id User-  , events      :: [Event]-  }-  deriving (Eq, Show, Generic)--instance FromJSON Events--data Event =-    EventMessage      { replyToken :: ReplyToken-                      , message    :: Message-                      , source     :: Source-                      , timestamp  :: EpochMilli-                      }-  | EventFollow       { replyToken :: ReplyToken-                      , source     :: Source-                      , timestamp  :: EpochMilli-                      }-  | EventUnfollow     { source    :: Source-                      , timestamp :: EpochMilli-                      }-  | EventJoin         { replyToken :: ReplyToken-                      , source     :: Source-                      , timestamp  :: EpochMilli-                      }-  | EventLeave        { source    :: Source-                      , timestamp :: EpochMilli-                      }-  | EventMemberJoined { replyToken :: ReplyToken-                      , source     :: Source-                      , timestamp  :: EpochMilli-                      , joined     :: Members-                      }-  | EventMemberLeft   { source    :: Source-                      , timestamp :: EpochMilli-                      , left      :: Members-                      }-  | EventPostback     { replyToken :: ReplyToken-                      , source     :: Source-                      , timestamp  :: EpochMilli-                      , postback   :: Postback-                      }-  | EventBeacon       { replyToken :: ReplyToken-                      , source     :: Source-                      , timestamp  :: EpochMilli-                      , beacon     :: Beacon-                      }-  | EventAccountLink  { replyToken :: ReplyToken-                      , source     :: Source-                      , timestamp  :: EpochMilli-                      , link       :: AccountLink-                      }-  | EventThings       { replyToken :: ReplyToken-                      , source     :: Source-                      , timestamp  :: EpochMilli-                      , things     :: Things-                      }-  deriving (Eq, Show, Generic)--instance FromJSON Event where-  parseJSON = genericParseJSON $-    defaultOptions { sumEncoding            = TaggedObject-                     { tagFieldName      = "type"-                     , contentsFieldName = undefined-                     }-                   , constructorTagModifier = (\(x : xs) -> toLower x : xs) . drop 5-                   }--data Message =-    Text     { messageId :: Text-             , text      :: Text-             }-  | Image    { messageId       :: Text-             , contentProvider :: ContentProvider-             }-  | Video    { messageId       :: Text-             , duration        :: Int-             , contentProvider :: ContentProvider-             }-  | Audio    { messageId       :: Text-             , duration        :: Int-             , contentProvider :: ContentProvider-             }-  | File     { messageId :: Text-             , fileSize  :: Int-             , fileName  :: Text-             }-  | Location { messageId :: Text-             , title     :: Text-             , address   :: Text-             , latitude  :: Double-             , longitude :: Double-             }-  | Sticker  { messageId :: Text-             , packageId :: Text-             , stickerId :: Text-             }-  deriving (Eq, Show, Generic)--messageJSONOptions :: Options-messageJSONOptions = defaultOptions-  { sumEncoding            = TaggedObject-    { tagFieldName      = "type"-    , contentsFieldName = undefined-    }-  , constructorTagModifier = fmap toLower-  , fieldLabelModifier     = \orig ->-      case L.stripPrefix "message" orig of-        Just s  -> fmap toLower s-        Nothing -> orig-  , omitNothingFields = True-  }--instance FromJSON Message where-  parseJSON = genericParseJSON messageJSONOptions---data ContentProvider = ContentProvider-  { originalContentUrl :: Maybe URL-  , previewImageUrl    :: Maybe URL-  }-  deriving (Eq, Show, Generic)--instance FromJSON ContentProvider--newtype EpochMilli = EpochMilli {-  fromEpochMilli :: UTCTime-  -- ^ Acquire the underlying value.-} deriving (Eq, Ord, Read, Show, FormatTime)--instance FromJSON EpochMilli where-  parseJSON = withScientific "EpochMilli" $ \t ->-    pure $ millis t-    where-      millis = EpochMilli-             . posixSecondsToUTCTime-             . fromRational-             . toRational-             . (/ 1000)---data Source =-    SourceUser (Id User)-  | SourceGroup (Id Group) (Maybe (Id User))-  | SourceRoom (Id Room) (Maybe (Id User))-  deriving (Eq, Show)--instance FromJSON Source where-  parseJSON = withObject "Source" $ \o -> do-    messageType <- o .: "type"-    case messageType of-      "user"  -> SourceUser  <$> o .: "userId"-      "group" -> SourceGroup <$> o .: "groupId" <*> o .:? "userId"-      "room"  -> SourceRoom  <$> o .: "roomId"  <*> o .:? "userId"-      _       -> fail ("unknown source: " ++ messageType)---data Members = Members { members :: [Source] }-  deriving (Eq, Show, Generic)--instance FromJSON Members--data PostbackDateTime =-    PostbackDay Day-  | PostbackLocalTime LocalTime-  | PostbackTimeOfDay TimeOfDay-  deriving (Eq, Show)--instance FromJSON PostbackDateTime where-  parseJSON = withObject "PostbackDateTime" $ \o -> do-    dateTime <- asum-      [ PostbackDay       <$> o .: "date"-      , PostbackLocalTime <$> o .: "datetime"-      , PostbackTimeOfDay <$> o .: "time"-      ]-    return dateTime--data Postback = Postback Text PostbackDateTime-  deriving (Eq, Show)--instance FromJSON Postback where-  parseJSON = withObject "Postback" $ \o -> do-    postbackData <- o .: "data"-    params       <- o .: "params"-    return $ Postback postbackData params--data BeaconEvent = Enter | Leave | Banner-  deriving (Show, Read, Eq, Ord, Generic)--instance FromJSON BeaconEvent where-  parseJSON = genericParseJSON $-    defaultOptions { constructorTagModifier = fmap toLower-                   , allNullaryToStringTag  = True-                   }--data Beacon = Beacon-   { hwid      :: Text-   , eventType :: BeaconEvent-   , dm        :: Maybe Text-   }-   deriving (Eq, Show, Generic)--instance FromJSON Beacon where-  parseJSON = withObject "Beacon" $ \o -> do-    hwid      <- o .:  "hwid"-    eventType <- o .:  "type"-    dm        <- o .:? "dm"-    return $ Beacon{..}--data AccountLinkResult = Ok | Failed- deriving (Eq, Show, Generic)--instance FromJSON AccountLinkResult where-  parseJSON = genericParseJSON $-    defaultOptions { constructorTagModifier = fmap toLower-                   , allNullaryToStringTag  = True-                   }--data AccountLink = AccountLink-   { nonce  :: Text-   , result :: AccountLinkResult-   }-   deriving (Eq, Show, Generic)--instance FromJSON AccountLink--data ThingsEvent = Link | Unlink-  deriving (Show, Read, Eq, Ord, Generic)--instance FromJSON ThingsEvent where-  parseJSON = genericParseJSON $-    defaultOptions { constructorTagModifier = fmap toLower-                   , allNullaryToStringTag  = True-                   }--data Things = Things-   { deviceId  :: Text-   , eventType :: ThingsEvent-   }-   deriving (Eq, Show, Generic)--instance FromJSON Things where-  parseJSON = withObject "Things" $ \o -> do-    deviceId  <- o .: "deviceId"-    eventType <- o .: "type"-    return $ Things{..}