POSSE
This commit is contained in:
parent
2ac8f81c9f
commit
52812abba2
|
@ -160,6 +160,12 @@ func main() {
|
|||
mi.RegisterPusher(mi.PushTwitter)
|
||||
go mi.StreamMastodonToTwitter(ctx)
|
||||
go mi.BlogPOSSE(ctx)
|
||||
} else {
|
||||
mi.RegisterPusher(func(ctx context.Context, p Post) error {
|
||||
ln.Log(ctx, p)
|
||||
fmt.Println(p.Format())
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
h := &http.Server{
|
||||
|
|
|
@ -27,4 +27,5 @@ func (mi *Mi) RegisterPusher(p Pusher) {
|
|||
func (mi *Mi) RegisterRoutes() {
|
||||
mi.mux.HandleFunc("/blog/refresh", mi.RefreshBlog)
|
||||
mi.mux.HandleFunc("/.within/botinfo", botInfoPage)
|
||||
mi.mux.HandleFunc("/posse/post", mi.PostPOSSE)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
@ -12,21 +14,32 @@ import (
|
|||
type Pusher func(context.Context, Post) error
|
||||
|
||||
type Post struct {
|
||||
Title string
|
||||
URL string
|
||||
Tags []string
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
Body string `json:"body"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
func (p Post) Format() string {
|
||||
var sb strings.Builder
|
||||
fmt.Fprintf(&sb, "New post: %s\n\n%s\n\n", p.Title, p.URL)
|
||||
if p.Title != "" {
|
||||
fmt.Fprintf(&sb, "%s\n\n", p.Title)
|
||||
}
|
||||
|
||||
if p.URL != "" {
|
||||
fmt.Fprintf(&sb, "%s\n\n", p.URL)
|
||||
}
|
||||
|
||||
if p.Body != "" {
|
||||
fmt.Fprintf(&sb, "%s\n\n", p.Body)
|
||||
}
|
||||
|
||||
for _, tg := range p.Tags {
|
||||
tg = strings.ReplaceAll(tg, "-", "")
|
||||
fmt.Fprintf(&sb, "#%s ", tg)
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
return strings.TrimSpace(sb.String())
|
||||
}
|
||||
|
||||
func (p Post) F() ln.F {
|
||||
|
@ -34,6 +47,7 @@ func (p Post) F() ln.F {
|
|||
"post_title": p.Title,
|
||||
"post_url": p.URL,
|
||||
"post_tags": p.Tags,
|
||||
"post_body": p.Body,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,3 +63,15 @@ func (mi *Mi) Push(ctx context.Context, p Post) error {
|
|||
|
||||
return result
|
||||
}
|
||||
|
||||
func (mi *Mi) PostPOSSE(w http.ResponseWriter, r *http.Request) {
|
||||
var data Post
|
||||
err := json.NewDecoder(r.Body).Decode(&data)
|
||||
if err != nil {
|
||||
http.Error(w, "bad data", http.StatusBadRequest)
|
||||
ln.Error(r.Context(), err)
|
||||
return
|
||||
}
|
||||
|
||||
mi.Push(r.Context(), data)
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ viewHeader currentRoute =
|
|||
]
|
||||
[ viewLink currentRoute ( "Mi", routes.top )
|
||||
, viewLink currentRoute ( "Switch Data", routes.switch )
|
||||
, viewLink currentRoute ( "POSSE", routes.pOSSE )
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module Mi exposing (TokenData, expectJson, request, tokenDecoder)
|
||||
module Mi exposing (TokenData, errorToString, expectJson, request, tokenDecoder)
|
||||
|
||||
import Http
|
||||
import Http exposing (Error(..))
|
||||
import Json.Decode as D
|
||||
|
||||
|
||||
|
@ -55,3 +55,22 @@ expectJson toMsg decoder =
|
|||
|
||||
Err err ->
|
||||
Err (Http.BadBody (D.errorToString err))
|
||||
|
||||
|
||||
errorToString : Http.Error -> String
|
||||
errorToString err =
|
||||
case err of
|
||||
Timeout ->
|
||||
"Timeout exceeded"
|
||||
|
||||
NetworkError ->
|
||||
"Network error"
|
||||
|
||||
BadStatus st ->
|
||||
"Bad status code: " ++ String.fromInt st
|
||||
|
||||
BadBody text ->
|
||||
"Unexpected response from api: " ++ text
|
||||
|
||||
BadUrl url ->
|
||||
"Malformed url: " ++ url
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
module Mi.POSSE exposing (..)
|
||||
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
type alias Post =
|
||||
{ title : String
|
||||
, body : String
|
||||
, url : String
|
||||
, tags : List String
|
||||
}
|
||||
|
||||
|
||||
encoder : Post -> E.Value
|
||||
encoder post =
|
||||
E.object
|
||||
[ ( "title", E.string post.title )
|
||||
, ( "body", E.string post.body )
|
||||
, ( "url", E.string post.url )
|
||||
, ( "tags", E.list E.string post.tags )
|
||||
]
|
||||
|
||||
|
||||
decoder : D.Decoder Post
|
||||
decoder =
|
||||
D.map4 Post
|
||||
(D.field "title" D.string)
|
||||
(D.field "body" D.string)
|
||||
(D.field "url" D.string)
|
||||
(D.field "tags" (D.list D.string))
|
|
@ -0,0 +1,169 @@
|
|||
module Pages.POSSE exposing (Model, Msg, page)
|
||||
|
||||
import Element exposing (..)
|
||||
import Element.Background as Background
|
||||
import Element.Font as Font
|
||||
import Element.Input as Input
|
||||
import Generated.Params as Params
|
||||
import Global
|
||||
import Http
|
||||
import Mi
|
||||
import Mi.POSSE as POSSE
|
||||
import Spa.Page
|
||||
import Utils.Spa exposing (Page, PageContext)
|
||||
|
||||
|
||||
page : Page Params.POSSE Model Msg model msg appMsg
|
||||
page =
|
||||
Spa.Page.component
|
||||
{ title = always "POSSE"
|
||||
, init = always init
|
||||
, update = update
|
||||
, subscriptions = always subscriptions
|
||||
, view = always view
|
||||
}
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ title : String
|
||||
, url : String
|
||||
, body : String
|
||||
, tags : String
|
||||
, status : String
|
||||
}
|
||||
|
||||
|
||||
init : Params.POSSE -> ( Model, Cmd Msg, Cmd Global.Msg )
|
||||
init _ =
|
||||
( { title = ""
|
||||
, url = ""
|
||||
, body = ""
|
||||
, tags = ""
|
||||
, status = ""
|
||||
}
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
type Msg
|
||||
= UpdateTitle String
|
||||
| UpdateBody String
|
||||
| UpdateURL String
|
||||
| UpdateTags String
|
||||
| Send
|
||||
| GotResponse (Result Http.Error String)
|
||||
|
||||
|
||||
update : PageContext -> Msg -> Model -> ( Model, Cmd Msg, Cmd Global.Msg )
|
||||
update { global } msg model =
|
||||
case msg of
|
||||
UpdateBody body ->
|
||||
( { model | body = body }
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
UpdateURL url ->
|
||||
( { model | url = url }
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
UpdateTags tags ->
|
||||
( { model | tags = tags }
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
UpdateTitle title ->
|
||||
( { model | title = title }
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Send ->
|
||||
let
|
||||
post =
|
||||
{ title = model.title
|
||||
, body = model.body
|
||||
, url = model.url
|
||||
, tags = String.words model.tags
|
||||
}
|
||||
|
||||
postJson =
|
||||
POSSE.encoder post
|
||||
in
|
||||
( model
|
||||
, Mi.request
|
||||
"POST"
|
||||
(Maybe.withDefault "" global.token)
|
||||
"/posse/post"
|
||||
(Http.jsonBody postJson)
|
||||
(Http.expectString GotResponse)
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
GotResponse resp ->
|
||||
case resp of
|
||||
Ok _ ->
|
||||
( { model | status = "Posted!" }
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Err data ->
|
||||
( { model | status = "Error when posting! " ++ Mi.errorToString data }
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions model =
|
||||
Sub.none
|
||||
|
||||
|
||||
view : Model -> Element Msg
|
||||
view model =
|
||||
let
|
||||
statusMsg =
|
||||
case model.status of
|
||||
"" ->
|
||||
none
|
||||
|
||||
_ ->
|
||||
row [] [ text "Status", text model.status ]
|
||||
|
||||
makeInput : String -> (String -> Msg) -> String -> Element Msg
|
||||
makeInput label msg text =
|
||||
Input.spellChecked [ padding 10, Font.size 14 ]
|
||||
{ label = Input.labelAbove [] (Element.text label)
|
||||
, onChange = msg
|
||||
, text = text
|
||||
, placeholder = Nothing
|
||||
}
|
||||
in
|
||||
column []
|
||||
[ statusMsg
|
||||
, row [ padding 10 ]
|
||||
[ makeInput "Title" UpdateTitle model.title
|
||||
, makeInput "URL" UpdateURL model.url
|
||||
, makeInput "Tags" UpdateTags model.tags
|
||||
]
|
||||
, Input.multiline [ Font.size 14 ]
|
||||
{ label =
|
||||
Input.labelAbove
|
||||
[ Input.focusedOnLoad ]
|
||||
(text "Body")
|
||||
, onChange = UpdateBody
|
||||
, spellcheck = True
|
||||
, placeholder = Nothing
|
||||
, text = model.body
|
||||
}
|
||||
, Input.button
|
||||
[]
|
||||
{ onPress = Just Send
|
||||
, label = text "Send"
|
||||
}
|
||||
]
|
|
@ -129,11 +129,12 @@ view model =
|
|||
|
||||
Nothing ->
|
||||
Element.column []
|
||||
[ Input.text []
|
||||
[ Input.currentPassword [ Input.focusedOnLoad ]
|
||||
{ label = Input.labelAbove [] (text "API Token")
|
||||
, onChange = UpdateToken
|
||||
, text = model.token
|
||||
, placeholder = Just (Input.placeholder [] (text ""))
|
||||
, show = False
|
||||
}
|
||||
, Input.button [] { onPress = Just SignIn, label = text "Login" }
|
||||
]
|
||||
|
|
|
@ -27,10 +27,6 @@ page =
|
|||
}
|
||||
|
||||
|
||||
|
||||
-- INIT
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ currentFront : Maybe Mi.SwitchData.Switch
|
||||
, frontData : Maybe (List Mi.SwitchData.Switch)
|
||||
|
@ -76,10 +72,6 @@ init { global } _ =
|
|||
)
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
||||
type Msg
|
||||
= ValidateCurrentFront (Result Http.Error Mi.SwitchData.Switch)
|
||||
| ValidateFrontData (Result Http.Error (List Mi.SwitchData.Switch))
|
||||
|
@ -126,8 +118,8 @@ update { global } msg model =
|
|||
, Cmd.none
|
||||
)
|
||||
|
||||
Err _ ->
|
||||
( { model | error = Just "can't fetch current front" }
|
||||
Err err ->
|
||||
( { model | error = Just ("can't fetch current front: " ++ Mi.errorToString err) }
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
@ -140,26 +132,18 @@ update { global } msg model =
|
|||
, Cmd.none
|
||||
)
|
||||
|
||||
Err _ ->
|
||||
( { model | error = Just "can't fetch historical front data" }
|
||||
Err err ->
|
||||
( { model | error = Just ("can't fetch historical front data: " ++ Mi.errorToString err) }
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- SUBSCRIPTIONS
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions model =
|
||||
Sub.none
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Model -> Element Msg
|
||||
view model =
|
||||
let
|
||||
|
|
Loading…
Reference in New Issue