refactor things to enable CLI mode
This commit is contained in:
parent
09c7eb8318
commit
c6cfdf9e9f
9 changed files with 101 additions and 49 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,4 +2,5 @@ node_modules/
|
||||||
frontend/dist/*.js
|
frontend/dist/*.js
|
||||||
frontend/.js
|
frontend/.js
|
||||||
underbbs
|
underbbs
|
||||||
|
underbbs-cli
|
||||||
__debug_*
|
__debug_*
|
10
README.md
10
README.md
|
@ -1,15 +1,23 @@
|
||||||
# underBBS
|
# underBBS
|
||||||
|
|
||||||
underBBS is a platform-agnostic messaging and social media client
|
underBBS is a protocol-agnostic decentralized social media client and toolkit
|
||||||
|
|
||||||
## design
|
## design
|
||||||
|
|
||||||
|
`underbbs` can run in two modes depending on its executable name:
|
||||||
|
|
||||||
|
### web client
|
||||||
|
|
||||||
`underbbs` supports multiple simultaneous account logins, mediating them for each user through a gateway server that handles all protocol-specific logic via `adapter`s and streaming content to the user through a single websocket connection with a singular data interface.
|
`underbbs` supports multiple simultaneous account logins, mediating them for each user through a gateway server that handles all protocol-specific logic via `adapter`s and streaming content to the user through a single websocket connection with a singular data interface.
|
||||||
|
|
||||||
each distinct `adapter` connection/configuration is represented in the frontend as a tab, and using the websocket's event-driven javascript interface with web components we can simply either store the data or tell the currently visible adapter that it might need to respond to the new data
|
each distinct `adapter` connection/configuration is represented in the frontend as a tab, and using the websocket's event-driven javascript interface with web components we can simply either store the data or tell the currently visible adapter that it might need to respond to the new data
|
||||||
|
|
||||||
adapters receive commands via a quartzgun web API and send data back on their shared websocket connection
|
adapters receive commands via a quartzgun web API and send data back on their shared websocket connection
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
`underbbs-cli` pulls adapter credentials from `~/.config/underbbs/cli.conf` and accepts commands on individual adapters, printing data to standard output.
|
||||||
|
|
||||||
## building and running
|
## building and running
|
||||||
|
|
||||||
requirements are
|
requirements are
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Adapter interface {
|
type Adapter interface {
|
||||||
Init(Settings, chan SocketData) error
|
Init(Settings, *chan SocketData) error
|
||||||
Name() string
|
Name() string
|
||||||
Subscribe(string) []error
|
Subscribe(string) []error
|
||||||
Fetch(string, []string) error
|
Fetch(string, []string) error
|
||||||
|
|
|
@ -4,10 +4,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
. "forge.lightcrystal.systems/lightcrystal/underbbs/models"
|
. "forge.lightcrystal.systems/lightcrystal/underbbs/models"
|
||||||
madon "github.com/McKael/madon"
|
madon "github.com/McKael/madon"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MastoAdapter struct {
|
type MastoAdapter struct {
|
||||||
data chan SocketData
|
data *chan SocketData
|
||||||
nickname string
|
nickname string
|
||||||
server string
|
server string
|
||||||
apiKey string
|
apiKey string
|
||||||
|
@ -21,11 +23,19 @@ type MastoAdapter struct {
|
||||||
|
|
||||||
var scopes = []string{"read", "write", "follow"}
|
var scopes = []string{"read", "write", "follow"}
|
||||||
|
|
||||||
|
func (self *MastoAdapter) send(data SocketData) {
|
||||||
|
if self.data != nil {
|
||||||
|
*self.data <- data
|
||||||
|
} else {
|
||||||
|
fmt.Println(os.Stdout, string(data.ToDatagram()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *MastoAdapter) Name() string {
|
func (self *MastoAdapter) Name() string {
|
||||||
return self.nickname
|
return self.nickname
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MastoAdapter) Init(settings Settings, data chan SocketData) error {
|
func (self *MastoAdapter) Init(settings Settings, data *chan SocketData) error {
|
||||||
self.nickname = settings.Nickname
|
self.nickname = settings.Nickname
|
||||||
self.server = *settings.Server
|
self.server = *settings.Server
|
||||||
self.apiKey = *settings.ApiKey
|
self.apiKey = *settings.ApiKey
|
||||||
|
@ -62,7 +72,7 @@ func (self *MastoAdapter) Subscribe(filter string) []error {
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
for e := range self.events {
|
for e := range self.events {
|
||||||
fmt.Println("event: %s !!!", e.Event)
|
log.Printf("event: %s !!!", e.Event)
|
||||||
switch e.Event {
|
switch e.Event {
|
||||||
case "error":
|
case "error":
|
||||||
case "update":
|
case "update":
|
||||||
|
@ -77,7 +87,7 @@ func (self *MastoAdapter) Subscribe(filter string) []error {
|
||||||
msg = self.mastoUpdateToMessage(v)
|
msg = self.mastoUpdateToMessage(v)
|
||||||
}
|
}
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
self.data <- msg
|
self.send(msg)
|
||||||
}
|
}
|
||||||
case "notification":
|
case "notification":
|
||||||
case "delete":
|
case "delete":
|
||||||
|
|
|
@ -9,13 +9,15 @@ import (
|
||||||
n "github.com/yitsushi/go-misskey/services/notes"
|
n "github.com/yitsushi/go-misskey/services/notes"
|
||||||
tl "github.com/yitsushi/go-misskey/services/notes/timeline"
|
tl "github.com/yitsushi/go-misskey/services/notes/timeline"
|
||||||
users "github.com/yitsushi/go-misskey/services/users"
|
users "github.com/yitsushi/go-misskey/services/users"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MisskeyAdapter struct {
|
type MisskeyAdapter struct {
|
||||||
data chan SocketData
|
data *chan SocketData
|
||||||
nickname string
|
nickname string
|
||||||
server string
|
server string
|
||||||
apiKey string
|
apiKey string
|
||||||
|
@ -31,19 +33,27 @@ type MisskeyAdapter struct {
|
||||||
stop chan bool
|
stop chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *MisskeyAdapter) send(data SocketData) {
|
||||||
|
if self.data != nil {
|
||||||
|
*self.data <- data
|
||||||
|
} else {
|
||||||
|
fmt.Fprintln(os.Stderr, string(data.ToDatagram()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *MisskeyAdapter) Name() string {
|
func (self *MisskeyAdapter) Name() string {
|
||||||
return self.nickname
|
return self.nickname
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MisskeyAdapter) Init(settings Settings, data chan SocketData) error {
|
func (self *MisskeyAdapter) Init(settings Settings, data *chan SocketData) error {
|
||||||
fmt.Println("initializing misskey adapter")
|
log.Print("initializing misskey adapter")
|
||||||
|
|
||||||
self.nickname = settings.Nickname
|
self.nickname = settings.Nickname
|
||||||
self.server = *settings.Server
|
self.server = *settings.Server
|
||||||
self.apiKey = *settings.ApiKey
|
self.apiKey = *settings.ApiKey
|
||||||
self.data = data
|
self.data = data
|
||||||
|
|
||||||
fmt.Println("getting ready to initialize internal client")
|
log.Print("getting ready to initialize internal client")
|
||||||
|
|
||||||
client, err := misskey.NewClientWithOptions(
|
client, err := misskey.NewClientWithOptions(
|
||||||
misskey.WithAPIToken(self.apiKey),
|
misskey.WithAPIToken(self.apiKey),
|
||||||
|
@ -51,10 +61,10 @@ func (self *MisskeyAdapter) Init(settings Settings, data chan SocketData) error
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
log.Print(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("misskey client initialized")
|
log.Print("misskey client initialized")
|
||||||
self.mk = client
|
self.mk = client
|
||||||
|
|
||||||
self.cache = make(map[string]time.Time)
|
self.cache = make(map[string]time.Time)
|
||||||
|
@ -119,10 +129,10 @@ func (self *MisskeyAdapter) poll() {
|
||||||
Limit: 100,
|
Limit: 100,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
log.Print(err.Error())
|
||||||
}
|
}
|
||||||
if merr != nil {
|
if merr != nil {
|
||||||
fmt.Println(merr.Error())
|
log.Print(merr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the cache for everything we just collected
|
// check the cache for everything we just collected
|
||||||
|
@ -131,13 +141,13 @@ func (self *MisskeyAdapter) poll() {
|
||||||
for _, n := range notes {
|
for _, n := range notes {
|
||||||
msg := self.toMessageIfNew(n)
|
msg := self.toMessageIfNew(n)
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
self.data <- msg
|
self.send(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, n := range mentions {
|
for _, n := range mentions {
|
||||||
msg := self.toMessageIfNew(n)
|
msg := self.toMessageIfNew(n)
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
self.data <- msg
|
self.send(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +160,7 @@ func (self *MisskeyAdapter) poll() {
|
||||||
Limit: 100,
|
Limit: 100,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
log.Print(err.Error())
|
||||||
}
|
}
|
||||||
for _, n := range notes {
|
for _, n := range notes {
|
||||||
msg := self.toMessageIfNew(n)
|
msg := self.toMessageIfNew(n)
|
||||||
|
@ -158,7 +168,7 @@ func (self *MisskeyAdapter) poll() {
|
||||||
latest = &probenote[0].CreatedAt
|
latest = &probenote[0].CreatedAt
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
self.data <- msg
|
self.send(msg)
|
||||||
}
|
}
|
||||||
if *latest == probenote[0].CreatedAt {
|
if *latest == probenote[0].CreatedAt {
|
||||||
break
|
break
|
||||||
|
@ -254,7 +264,7 @@ func (self *MisskeyAdapter) toAuthor(usr mkm.User, bustCache bool) *Author {
|
||||||
}
|
}
|
||||||
|
|
||||||
if bustCache || !exists || (updated != nil && timestamp.Before(time.UnixMilli(*updated))) || timestamp.Before(*usr.CreatedAt) {
|
if bustCache || !exists || (updated != nil && timestamp.Before(time.UnixMilli(*updated))) || timestamp.Before(*usr.CreatedAt) {
|
||||||
fmt.Println("converting author: " + usr.ID)
|
log.Print("converting author: " + usr.ID)
|
||||||
if usr.UpdatedAt != nil {
|
if usr.UpdatedAt != nil {
|
||||||
self.cache[authorId] = *usr.UpdatedAt
|
self.cache[authorId] = *usr.UpdatedAt
|
||||||
} else {
|
} else {
|
||||||
|
@ -291,7 +301,7 @@ func (self *MisskeyAdapter) Fetch(etype string, ids []string) error {
|
||||||
} else {
|
} else {
|
||||||
msg := self.toMessage(data, true)
|
msg := self.toMessage(data, true)
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
self.data <- msg
|
self.send(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "children":
|
case "children":
|
||||||
|
@ -305,7 +315,7 @@ func (self *MisskeyAdapter) Fetch(etype string, ids []string) error {
|
||||||
for _, n := range data {
|
for _, n := range data {
|
||||||
msg := self.toMessage(n, true)
|
msg := self.toMessage(n, true)
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
self.data <- msg
|
self.send(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +330,7 @@ func (self *MisskeyAdapter) Fetch(etype string, ids []string) error {
|
||||||
for _, n := range data {
|
for _, n := range data {
|
||||||
msg := self.toMessage(n, true)
|
msg := self.toMessage(n, true)
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
self.data <- msg
|
self.send(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,7 +348,6 @@ func (self *MisskeyAdapter) Fetch(etype string, ids []string) error {
|
||||||
hostPtr = &host
|
hostPtr = &host
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmt.Printf("attempting user resolution: @%s@%s\n", user, host)
|
|
||||||
data, err := self.mk.Users().Show(users.ShowRequest{
|
data, err := self.mk.Users().Show(users.ShowRequest{
|
||||||
Username: &user,
|
Username: &user,
|
||||||
Host: hostPtr,
|
Host: hostPtr,
|
||||||
|
@ -348,7 +357,7 @@ func (self *MisskeyAdapter) Fetch(etype string, ids []string) error {
|
||||||
} else {
|
} else {
|
||||||
a := self.toAuthor(data, false)
|
a := self.toAuthor(data, false)
|
||||||
if a != nil {
|
if a != nil {
|
||||||
self.data <- a
|
self.send(a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,21 +7,31 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
. "forge.lightcrystal.systems/lightcrystal/underbbs/models"
|
. "forge.lightcrystal.systems/lightcrystal/underbbs/models"
|
||||||
nostr "github.com/nbd-wtf/go-nostr"
|
nostr "github.com/nbd-wtf/go-nostr"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NostrAdapter struct {
|
type NostrAdapter struct {
|
||||||
data chan SocketData
|
data *chan SocketData
|
||||||
nickname string
|
nickname string
|
||||||
privkey string
|
privkey string
|
||||||
relays []*nostr.Relay
|
relays []*nostr.Relay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *NostrAdapter) send(data SocketData) {
|
||||||
|
if self.data != nil {
|
||||||
|
*self.data <- data
|
||||||
|
} else {
|
||||||
|
fmt.Fprintln(os.Stdout, string(data.ToDatagram()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *NostrAdapter) Name() string {
|
func (self *NostrAdapter) Name() string {
|
||||||
return self.nickname
|
return self.nickname
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *NostrAdapter) Init(settings Settings, data chan SocketData) error {
|
func (self *NostrAdapter) Init(settings Settings, data *chan SocketData) error {
|
||||||
self.nickname = settings.Nickname
|
self.nickname = settings.Nickname
|
||||||
self.privkey = *settings.PrivKey
|
self.privkey = *settings.PrivKey
|
||||||
self.data = data
|
self.data = data
|
||||||
|
@ -47,35 +57,32 @@ func (self *NostrAdapter) Subscribe(filter string) []error {
|
||||||
|
|
||||||
errs := make([]error, 0)
|
errs := make([]error, 0)
|
||||||
|
|
||||||
fmt.Print("unmarshalled filter from json; iterating through relays to subscribe..")
|
log.Print("unmarshalled filter from json; iterating through relays to subscribe...")
|
||||||
|
|
||||||
for _, r := range self.relays {
|
for _, r := range self.relays {
|
||||||
fmt.Print(".")
|
|
||||||
sub, err := r.Subscribe(context.Background(), filters)
|
sub, err := r.Subscribe(context.Background(), filters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
} else {
|
} else {
|
||||||
go func() {
|
go func() {
|
||||||
for ev := range sub.Events {
|
for ev := range sub.Events {
|
||||||
fmt.Print("!")
|
|
||||||
// try sequentially to encode into an underbbs object
|
// try sequentially to encode into an underbbs object
|
||||||
// and send it to the appropriate channel
|
// and send it to the appropriate channel
|
||||||
m, err := self.nostrEventToMsg(ev)
|
m, err := self.nostrEventToMsg(ev)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
self.data <- m
|
self.send(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
fmt.Println()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
fmt.Println("subscription operation completed with errors")
|
log.Print("subscription operation completed with errors")
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
fmt.Println("subscription operation completed without errors")
|
log.Print("subscription operation completed without errors")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"hacklab.nilfm.cc/quartzgun/router"
|
"hacklab.nilfm.cc/quartzgun/router"
|
||||||
"hacklab.nilfm.cc/quartzgun/util"
|
"hacklab.nilfm.cc/quartzgun/util"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -33,16 +34,14 @@ func getSubscriberByKey(key string, subscribers map[*Subscriber][]adapter.Adapte
|
||||||
|
|
||||||
func setAdaptersForSubscriber(key string, adapters []adapter.Adapter, subscribers map[*Subscriber][]adapter.Adapter) error {
|
func setAdaptersForSubscriber(key string, adapters []adapter.Adapter, subscribers map[*Subscriber][]adapter.Adapter) error {
|
||||||
var ptr *Subscriber = nil
|
var ptr *Subscriber = nil
|
||||||
fmt.Print("looking for subscriber in map..")
|
log.Print("looking for subscriber in map...")
|
||||||
for s, _ := range subscribers {
|
for s, _ := range subscribers {
|
||||||
fmt.Print(".")
|
|
||||||
if s.key == key {
|
if s.key == key {
|
||||||
ptr = s
|
ptr = s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println()
|
|
||||||
if ptr != nil {
|
if ptr != nil {
|
||||||
fmt.Println("setting adaters for the found subscriber: " + ptr.key)
|
log.Print("setting adaters for the found subscriber: " + ptr.key)
|
||||||
subscribers[ptr] = adapters
|
subscribers[ptr] = adapters
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -85,7 +84,7 @@ func apiConfigureAdapters(next http.Handler, subscribers map[*Subscriber][]adapt
|
||||||
break
|
break
|
||||||
|
|
||||||
}
|
}
|
||||||
err := a.Init(s, subscriber.data)
|
err := a.Init(s, &subscriber.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.AddContextValue(req, "data", err.Error())
|
util.AddContextValue(req, "data", err.Error())
|
||||||
w.WriteHeader(500)
|
w.WriteHeader(500)
|
||||||
|
@ -93,13 +92,13 @@ func apiConfigureAdapters(next http.Handler, subscribers map[*Subscriber][]adapt
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("adapter initialized - subscribing with default filter")
|
log.Print("adapter initialized - subscribing with default filter")
|
||||||
|
|
||||||
errs := a.Subscribe(a.DefaultSubscriptionFilter())
|
errs := a.Subscribe(a.DefaultSubscriptionFilter())
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
errMsg := ""
|
errMsg := ""
|
||||||
for _, e := range errs {
|
for _, e := range errs {
|
||||||
fmt.Println("processing an error")
|
log.Print("processing an error")
|
||||||
errMsg += fmt.Sprintf("- %s\n", e.Error())
|
errMsg += fmt.Sprintf("- %s\n", e.Error())
|
||||||
}
|
}
|
||||||
util.AddContextValue(req, "data", errMsg)
|
util.AddContextValue(req, "data", errMsg)
|
||||||
|
@ -108,10 +107,10 @@ func apiConfigureAdapters(next http.Handler, subscribers map[*Subscriber][]adapt
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("adapter ready for use; adding to array")
|
log.Print("adapter ready for use; adding to array")
|
||||||
|
|
||||||
adapters = append(adapters, a)
|
adapters = append(adapters, a)
|
||||||
fmt.Println("adapter added to array")
|
log.Print("adapter added to array")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: cancel subscriptions on any existing adapters
|
// TODO: cancel subscriptions on any existing adapters
|
||||||
|
@ -169,7 +168,7 @@ func apiAdapterFetch(next http.Handler, subscribers map[*Subscriber][]adapter.Ad
|
||||||
if a.Name() == apiParams["adapter_id"] {
|
if a.Name() == apiParams["adapter_id"] {
|
||||||
err := a.Fetch(queryParams["entity_type"][0], queryParams["entity_id"])
|
err := a.Fetch(queryParams["entity_type"][0], queryParams["entity_id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
log.Print(err.Error())
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(http.StatusAccepted)
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package server
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"forge.lightcrystal.systems/lightcrystal/underbbs/adapter"
|
"forge.lightcrystal.systems/lightcrystal/underbbs/adapter"
|
||||||
"forge.lightcrystal.systems/lightcrystal/underbbs/models"
|
"forge.lightcrystal.systems/lightcrystal/underbbs/models"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
@ -90,14 +89,14 @@ func (self *BBSServer) subscribeHandler(w http.ResponseWriter, r *http.Request)
|
||||||
defer c.Close(websocket.StatusInternalError, "")
|
defer c.Close(websocket.StatusInternalError, "")
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
fmt.Println("waiting for data on the subscriber's channel")
|
self.logf("waiting for data on the subscriber's channel")
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case msg := <-s.msgs:
|
case msg := <-s.msgs:
|
||||||
writeTimeout(ctx, time.Second*5, c, msg)
|
writeTimeout(ctx, time.Second*5, c, msg)
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
fmt.Println("subscriber has disconnected")
|
self.logf("subscriber has disconnected")
|
||||||
close(s.data)
|
close(s.data)
|
||||||
return //ctx.Err()
|
return //ctx.Err()
|
||||||
}
|
}
|
||||||
|
@ -110,7 +109,7 @@ func (self *BBSServer) subscribeHandler(w http.ResponseWriter, r *http.Request)
|
||||||
// block on the data channel, serializing and passing the data to the subscriber
|
// block on the data channel, serializing and passing the data to the subscriber
|
||||||
listen([]chan models.SocketData{s.data}, s.msgs)
|
listen([]chan models.SocketData{s.data}, s.msgs)
|
||||||
|
|
||||||
fmt.Println("data listener is done!")
|
self.logf("data listener is done!")
|
||||||
|
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
return
|
return
|
||||||
|
|
23
underbbs.go
23
underbbs.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -14,13 +15,31 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := run()
|
|
||||||
|
args := os.Args
|
||||||
|
|
||||||
|
var err error = nil
|
||||||
|
|
||||||
|
switch filepath.Base(args[0]) {
|
||||||
|
case "underbbs-cli":
|
||||||
|
err = run_cli(args[1:]...)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
err = run_srvr()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func run() error {
|
func run_cli(args ...string) error {
|
||||||
|
log.Print("test!!")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func run_srvr() error {
|
||||||
l, err := net.Listen("tcp", ":"+strconv.FormatInt(int64(9090), 10))
|
l, err := net.Listen("tcp", ":"+strconv.FormatInt(int64(9090), 10))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in a new issue