Created
December 20, 2019 17:19
-
-
Save y2k/2dee901838eb763fe196d240e9442331 to your computer and use it in GitHub Desktop.
hackathon
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open System | |
open FSharp.Data | |
type OnboardingType = XmlProvider<".data/onboarding.xml"> | |
module Domain = | |
open SlackAPI | |
let toBlocks (cmd : OnboardingType.Command) : IBlock array = | |
cmd.Items | |
|> Seq.map ^ fun x -> | |
match x.Cmd with | |
| Some cmdId -> | |
SectionBlock( | |
text = Text(text = x.Value, ``type`` = TextTypes.Markdown), | |
accessory = ButtonElement(value = cmdId, text = Text(text = "Открыть"))) | |
| None -> | |
SectionBlock(text = Text(text = x.Value, ``type`` = TextTypes.Markdown)) | |
:> IBlock | |
|> Seq.append [ DividerBlock() ] | |
|> Seq.toArray | |
let handleNewMessage (u : User) (cmd : string) (onboarding : OnboardingType.Commands) = | |
onboarding.Commands | |
|> Seq.filter ^ fun x -> String.equalsCaseInsensitive x.Cmd cmd | |
|> Seq.map toBlocks | |
|> Seq.tryExactlyOne | |
|> Option.defaultWith ^ fun _ -> onboarding.Commands |> Array.find (fun x -> x.Cmd = "default") |> toBlocks | |
module DropboxStorage = | |
open Dropbox.Api | |
let read (client : DropboxClient) = async { | |
let! a = client.Files.DownloadAsync("/onboarding.xml") |> Async.AwaitTask | |
return! a.GetContentAsStringAsync() |> Async.AwaitTask } | |
type UserId = UserId of name : string * userId : string * channelId : string | |
type Command = Command of string | |
module Bot = | |
let instance : (UserId -> Command -> unit) ref = ref (fun _ _ -> ()) | |
module Server = | |
open Suave | |
open Suave.Filters | |
open Suave.Operators | |
open Suave.Successful | |
type JsonTypes = JsonProvider<".data/slack-call-example.json"> | |
let handlePost = | |
request ^ fun ctx -> | |
let r = | |
ctx.formData "payload" | |
|> Choice.orDefault ^ fun _ -> failwith "???" | |
|> JsonTypes.Parse | |
!Bot.instance (UserId (r.User.Name, r.User.Id, r.Channel.Id)) (Command r.Actions.[0].Value) | |
OK "" | |
let start () = | |
choose [ POST >=> path "/" >=> handlePost ] | |
|> startWebServer { | |
defaultConfig with | |
bindings = [ HttpBinding.create HTTP (System.Net.IPAddress.Parse "0.0.0.0") 8080us ] } | |
open SlackAPI | |
open SlackAPI.WebSocketMessages | |
[<EntryPoint>] | |
let main args = | |
let onMessage (client : SlackSocketClient) (nm : NewMessage) = | |
!Bot.instance (UserId (nm.username, nm.user, nm.channel)) (Command ^ nm.text) | |
let client = SlackSocketClient(args.[0]) | |
client.add_OnMessageReceived ^ Action<_> (onMessage client) | |
let dropbox = new Dropbox.Api.DropboxClient(args.[1]) | |
Bot.instance := | |
fun (UserId (userName, userId, channelId)) (Command command) -> | |
async { | |
let user = client.Users |> Seq.tryFind (fun u -> u.id = userId) | |
match user with | |
| Some user -> | |
let! onboardingXml = DropboxStorage.read dropbox | |
let result = | |
OnboardingType.Parse onboardingXml | |
|> Domain.handleNewMessage user command | |
client.PostMessage(Action<_> (printfn "PostMessage = %O"), channelId, "", blocks = result) | |
| None -> | |
printfn "User not found: %s (%s)" channelId userName | |
} |> Async.Start | |
client.Connect(fun r -> printfn "Connected: %O (%O)" r.ok r.error) | |
Server.start () | |
0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment