Skip to content

Instantly share code, notes, and snippets.

@y2k
Created December 20, 2019 17:19
Show Gist options
  • Save y2k/2dee901838eb763fe196d240e9442331 to your computer and use it in GitHub Desktop.
Save y2k/2dee901838eb763fe196d240e9442331 to your computer and use it in GitHub Desktop.
hackathon
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