POSSE
This commit is contained in:
parent
2ac8f81c9f
commit
52812abba2
|
@ -160,6 +160,12 @@ func main() {
|
||||||
mi.RegisterPusher(mi.PushTwitter)
|
mi.RegisterPusher(mi.PushTwitter)
|
||||||
go mi.StreamMastodonToTwitter(ctx)
|
go mi.StreamMastodonToTwitter(ctx)
|
||||||
go mi.BlogPOSSE(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{
|
h := &http.Server{
|
||||||
|
|
|
@ -27,4 +27,5 @@ func (mi *Mi) RegisterPusher(p Pusher) {
|
||||||
func (mi *Mi) RegisterRoutes() {
|
func (mi *Mi) RegisterRoutes() {
|
||||||
mi.mux.HandleFunc("/blog/refresh", mi.RefreshBlog)
|
mi.mux.HandleFunc("/blog/refresh", mi.RefreshBlog)
|
||||||
mi.mux.HandleFunc("/.within/botinfo", botInfoPage)
|
mi.mux.HandleFunc("/.within/botinfo", botInfoPage)
|
||||||
|
mi.mux.HandleFunc("/posse/post", mi.PostPOSSE)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
|
@ -12,21 +14,32 @@ import (
|
||||||
type Pusher func(context.Context, Post) error
|
type Pusher func(context.Context, Post) error
|
||||||
|
|
||||||
type Post struct {
|
type Post struct {
|
||||||
Title string
|
Title string `json:"title"`
|
||||||
URL string
|
URL string `json:"url"`
|
||||||
Tags []string
|
Body string `json:"body"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Post) Format() string {
|
func (p Post) Format() string {
|
||||||
var sb strings.Builder
|
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 {
|
for _, tg := range p.Tags {
|
||||||
tg = strings.ReplaceAll(tg, "-", "")
|
tg = strings.ReplaceAll(tg, "-", "")
|
||||||
fmt.Fprintf(&sb, "#%s ", tg)
|
fmt.Fprintf(&sb, "#%s ", tg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.String()
|
return strings.TrimSpace(sb.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Post) F() ln.F {
|
func (p Post) F() ln.F {
|
||||||
|
@ -34,6 +47,7 @@ func (p Post) F() ln.F {
|
||||||
"post_title": p.Title,
|
"post_title": p.Title,
|
||||||
"post_url": p.URL,
|
"post_url": p.URL,
|
||||||
"post_tags": p.Tags,
|
"post_tags": p.Tags,
|
||||||
|
"post_body": p.Body,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,3 +63,15 @@ func (mi *Mi) Push(ctx context.Context, p Post) error {
|
||||||
|
|
||||||
return result
|
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 ( "Mi", routes.top )
|
||||||
, viewLink currentRoute ( "Switch Data", routes.switch )
|
, 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
|
import Json.Decode as D
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,3 +55,22 @@ expectJson toMsg decoder =
|
||||||
|
|
||||||
Err err ->
|
Err err ->
|
||||||
Err (Http.BadBody (D.errorToString 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 ->
|
Nothing ->
|
||||||
Element.column []
|
Element.column []
|
||||||
[ Input.text []
|
[ Input.currentPassword [ Input.focusedOnLoad ]
|
||||||
{ label = Input.labelAbove [] (text "API Token")
|
{ label = Input.labelAbove [] (text "API Token")
|
||||||
, onChange = UpdateToken
|
, onChange = UpdateToken
|
||||||
, text = model.token
|
, text = model.token
|
||||||
, placeholder = Just (Input.placeholder [] (text ""))
|
, placeholder = Just (Input.placeholder [] (text ""))
|
||||||
|
, show = False
|
||||||
}
|
}
|
||||||
, Input.button [] { onPress = Just SignIn, label = text "Login" }
|
, Input.button [] { onPress = Just SignIn, label = text "Login" }
|
||||||
]
|
]
|
||||||
|
|
|
@ -27,10 +27,6 @@ page =
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- INIT
|
|
||||||
|
|
||||||
|
|
||||||
type alias Model =
|
type alias Model =
|
||||||
{ currentFront : Maybe Mi.SwitchData.Switch
|
{ currentFront : Maybe Mi.SwitchData.Switch
|
||||||
, frontData : Maybe (List Mi.SwitchData.Switch)
|
, frontData : Maybe (List Mi.SwitchData.Switch)
|
||||||
|
@ -76,10 +72,6 @@ init { global } _ =
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- UPDATE
|
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= ValidateCurrentFront (Result Http.Error Mi.SwitchData.Switch)
|
= ValidateCurrentFront (Result Http.Error Mi.SwitchData.Switch)
|
||||||
| ValidateFrontData (Result Http.Error (List Mi.SwitchData.Switch))
|
| ValidateFrontData (Result Http.Error (List Mi.SwitchData.Switch))
|
||||||
|
@ -126,8 +118,8 @@ update { global } msg model =
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
Err _ ->
|
Err err ->
|
||||||
( { model | error = Just "can't fetch current front" }
|
( { model | error = Just ("can't fetch current front: " ++ Mi.errorToString err) }
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
@ -140,26 +132,18 @@ update { global } msg model =
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
Err _ ->
|
Err err ->
|
||||||
( { model | error = Just "can't fetch historical front data" }
|
( { model | error = Just ("can't fetch historical front data: " ++ Mi.errorToString err) }
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- SUBSCRIPTIONS
|
|
||||||
|
|
||||||
|
|
||||||
subscriptions : Model -> Sub Msg
|
subscriptions : Model -> Sub Msg
|
||||||
subscriptions model =
|
subscriptions model =
|
||||||
Sub.none
|
Sub.none
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- VIEW
|
|
||||||
|
|
||||||
|
|
||||||
view : Model -> Element Msg
|
view : Model -> Element Msg
|
||||||
view model =
|
view model =
|
||||||
let
|
let
|
||||||
|
|
Loading…
Reference in New Issue