Skip to content

Commit

Permalink
Feature/skychat: basic p2p and group chat implementation (#1494)
Browse files Browse the repository at this point in the history
* add skychat rework ; begin to fix make format check errors

* fix some make check errors

* Fix linting and naming in package notification

* comment unused server package

* Fix Fprint linting

* Fix return error lint and add todo

* Fix error check linting in New() of ClientRepo

* Fix Global comments in package memory

* Minor fix

* Fix spelling of method IsEmtpy of Client

* Cleanup package memory

* Remove unnecessary print line

* Add package-comments and fix global comments

* Minor fix

* Fix linting in cli commands

* Fix linting in cli visor tp

* Fixed and added comments in message package of domain

* Minor Fix

* Fix linting

* Minor update

* handle some errors in a temporary fashion

* commit

commit to merge develop into branch

* commit

* commit

* small changes

* next commit

* [backend] add un/mute peer functionality

* fix check-windows output

* fix build path in windows

the build path of the apps was changed from ./apps to ./build/apps in linux, but not in windows. This change fixes the build path on windows

* fix to stop hangups

sometimes the processing of the sent messages seem to hangup, this fix looks like it helps to prevent those hangups

* export User attributes

* remove unused exported Interface function

* add boltdb for user repository

* add RejectMessage to P2P

* fix make-check errs

* turn function call into go routine

* fix darwin make format errs

* add usecases to hire and fire moderator

* add cli functionality

With this commit cli functionality can be integrated into the app, but the config entries inside skywire-config.json have to be changed to be:
{
    "name": "skychat",
    "binary": "skychat",
    "args": ["--addr=:8001"],
    "auto_start": true,
    "port": 1
   },
This was changed in the default app config generation.

* improve cli functionality with rpc

implement rpc server so appservices can be launched from the cli as rpc client.
First implemented usecase is sending textmessages via cli.

* fix make-check errs

* small rpc fix

* fix sending large info

When setting a large image in the info, the app crashed.
The app also crashed while trying to log the big IMG entry inside info.

* fix make-check errs

* visor repository with boltdb

Got visor repository working with boltdb and changed service to use boltdb instead of memory.
Memory repositories will stay to be able to use skychat with a flag on 'memory'/'privacy' mode.

* relocate todos

* first refactoring for more readability

Effort to make it easier to understand what happens inside the app.
More refactoring might be needed inside the /app/chat (usecases) folder

* refactoring for better readability

* refactor delete to only delete local instances of chats and groups

* refactoring for better readability

* further refactoring and bufixing

* fix make check errs

* fix make check errs

had to update to golanci-lint > 1.52.1 to catch new errs

* fix make check errs

* fix ipc client naming

* fix build path for autodetection of config gen

* fix skychat default flag

* add dependencies for skychat

* fix skywire.conf for latest commits

* fix build path in Readme

* Add new Skychat Readme [WIP]

* first try to implement plantuml rendering into skychat readme

* skychat: next try rendering plantuml inside readme

* skychat: fix file ending for plantuml rendering inside readme

* websockets for notifications & refactoring for future implementation of dmsg

* Update go mod

* fix cli skychat banner, and merge problem

* change .db  files in gitignore

* fix import link for skychat in skywire

* export skychat RootCmd for cobra

* fix skychat import link in skywire-deployment

* move cli out of internal and fix imports

---------

Co-authored-by: Moses Narrow <moe_narrow@use.startmail.com>
Co-authored-by: ersonp <ersonpereiracr7@gmail.com>
Co-authored-by: Moses Narrow <36607567+0pcom@users.noreply.github.com>
  • Loading branch information
4 people authored Mar 14, 2024
1 parent 9d80774 commit 4c200f6
Show file tree
Hide file tree
Showing 149 changed files with 20,070 additions and 1,499 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pkg/visor/foo/

/bin
/node
/users.db
/*.db
/hypervisor
/*-node
/*-visor
Expand Down
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,12 @@ example-apps: ## Build example apps
${OPTS} go build ${BUILD_OPTS} -o $(BUILD_PATH)apps/ ./example/...

host-apps-windows: ## build apps on windows
powershell -Command new-item $(BUILD_PATH)apps -itemtype directory -force
powershell 'Get-ChildItem .\cmd\apps | % { ${OPTS} go build ${BUILD_OPTS} -o $(BUILD_PATH)apps $$_.FullName }'
powershell -Command new-item $(BUILD_PATH)apps/ -itemtype directory -force
powershell 'Get-ChildItem .\cmd\apps | % { ${OPTS} go build ${BUILD_OPTS} -o $(BUILD_PATH)apps/ $$_.FullName }'

host-apps-windows-appveyor: ## build apps on windows. `go build` with ${OPTS} for AppVeyor image
powershell -Command new-item $(BUILD_PATH)apps/ -itemtype directory -force
powershell 'Get-ChildItem .\cmd\apps | % { ${OPTS} go build -o $(BUILD_PATH)apps/ $$_.FullName }'

# Static Apps
host-apps-static: ## Build app
Expand Down
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,25 +120,29 @@ git checkout develop
make build1
```

To compile skywire directly from source archive, first download the latest source archive from the release section with your browser or another utility. Extract it with an archiving utility, enter the directory where the sources were extracted, and run `make build1`.
To compile skywire directly from source archive, first download the latest source archive from the release section with your browser or another utility. Extract it with an archiving utility, enter the directory where the sources were extracted, and run `make build`.


`make build1` builds the binaries and apps with `go build`
`make build` builds the binaries and apps with `go build`

`skywire-cli` and `skywire-visor` binaries will populate in the current directory; app binaries will populate the `apps` directory.
`skywire-cli` and `skywire-visor` binaries will populate in the `build` directory; app binaries will populate the `build\apps` directory.

Build output:

```
├──skywire-cli
└─┬skywire-visor
└─┬apps
├──skychat
├──skysocks
├──skysocks-client
├──vpn-client
├──vpn-server
└──skychat
build
└─┬──setup-node
├──skywire-cli
├──skywire-systray
├──skywire-visor
└─┬skywire
└─┬apps
├──skychat
├──skysocks
├──skysocks-client
├──vpn-client
├──vpn-server
└──skychat
```

'install' these executables to the `GOPATH`:
Expand All @@ -153,7 +157,7 @@ For more options, run `make help`.
To run skywire from this point, first generate a config.

```
./skywire-cli config gen -birx
./build/skywire-cli config gen -birx
```
`-b --bestproto` use the best protocol (dmsg | direct) to connect to the skywire production deployment
`-i --ishv` create a local hypervisor configuration
Expand Down
93 changes: 47 additions & 46 deletions cmd/apps/skychat/README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,54 @@
# Skywire Chat app
# Skywire Chat App

Chat implements basic text messaging between skywire visors.

It is possible to send messages p2p or in groups.

The group feature is structured in a way that it is possible for everyone to host and join multiple servers.

Those servers are structured like that:

- Public Key of Visor
- Public Key of Server 1
- Public Key of Room 1.1
- Public Key of Room 1.2
- ...
- Public Key of Server 2
- Public Key of Room 2.1
- Public Key of Room 2.2

And the chats are adressed with a so called public key route (pkroute):
- Route to a Room = [PK of Visor, PK of Server, PK of Room]
- P2P Route = [PK of Visor, PK of Visor, PK of Visor]


Messaging UI is exposed via web interface.

Chat only supports one WEB client user at a time.

## Local setup

Create 2 visor config files:

`skywire1.json`

```json
{
"apps": [
{
"app": "skychat",
"version": "1.0",
"auto_start": true,
"port": 1
}
]
}
```

`skywire2.json`

```json
{
"apps": [
{
"app": "skychat",
"version": "1.0",
"auto_start": true,
"port": 1,
"args": ["-addr", ":8002"]
}
]
}
```

Compile binaries and start 2 visors:

```bash
$ go build -o ./build/apps/skychat.v1.0 ./cmd/apps/skychat
$ cd ./build
$ ./skywire-visor skywire1.json
$ ./skywire-visor skywire2.json
```

Chat interface will be available on ports `8001` and `8002`.

# Development Info
The app is written with 'Clean Architecture' based on the blog entry of Panayiotis Kritiotis [Clean Architecture in Go](https://pkritiotis.io/clean-architecture-in-golang/)

To get a basic understanding on how it is structured, reading the blog will help.

## Sequence Diagrams
### Init
![Init](http://plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/4rchim3d3s/skywire-mainnet/feature/skychat/cmd/apps/skychat/doc/init.iuml)

### MessengerService.Listen
![MessengerService.Listen](http://plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/4rchim3d3s/skywire-mainnet/feature/skychat/cmd/apps/skychat/doc/messengerServiceListen.iuml)

### MessengerService.Handle
![Init](http://plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/4rchim3d3s/skywire-mainnet/feature/skychat/cmd/apps/skychat/doc/messengerServiceHandle.iuml)

### MessengerService.handleP2PMessage
![Init](http://plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/4rchim3d3s/skywire-mainnet/feature/skychat/cmd/apps/skychat/doc/messengerServiceHandleP2PMessage.iuml)

### MessengerService.handleRemoteServerMessage (This is the client-side handling of servers)
TODO
### MessengerService.handleLocalServerMessage (This is the server-side handling of servers)
TODO

### Usecases
TODO
18 changes: 18 additions & 0 deletions cmd/apps/skychat/cli/chat/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Package clichat contains code for chat command of cli inputports
package clichat

import (
"github.com/spf13/cobra"

clichatsend "github.com/skycoin/skywire/cmd/apps/skychat/cli/chat/send"
)

// RootCmd is the sub-command so interact with the chats
var RootCmd = &cobra.Command{
Use: "chat",
Short: "Send messages or query a chat",
}

func init() {
RootCmd.AddCommand(clichatsend.SendCmd)
}
14 changes: 14 additions & 0 deletions cmd/apps/skychat/cli/chat/send/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Package clichatsend contains code of the cobra cli chat send commands
package clichatsend

import "github.com/spf13/cobra"

// SendCmd is the sub-command to send messages
var SendCmd = &cobra.Command{
Use: "send",
Short: "Send messages",
}

func init() {
SendCmd.AddCommand(textMessageCmd)
}
43 changes: 43 additions & 0 deletions cmd/apps/skychat/cli/chat/send/textmessage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package clichatsend

import (
"fmt"

"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/skycoin/skywire-utilities/pkg/cipher"
"github.com/skycoin/skywire/cmd/apps/skychat/internal/inputports"
)

var textMessageCmd = &cobra.Command{
Use: "text <vpk> <spk> <rpk> <msg>",
Short: "Send text message",
Args: cobra.MinimumNArgs(4),
Run: func(cmd *cobra.Command, args []string) {
vpk := ParsePK(cmd.Flags(), "vpk", args[0])
spk := ParsePK(cmd.Flags(), "spk", args[1])
rpk := ParsePK(cmd.Flags(), "rpk", args[2])
msg := args[3]

fmt.Println("SendTextMessage via cli (cli)")
fmt.Println(msg)
fmt.Printf("to v: %s s: %s, r %s\n", vpk.Hex(), spk.Hex(), rpk.Hex())

err := inputports.InputportsServices.RPCClient.SendTextMessage(vpk, spk, rpk, msg)
if err != nil {
fmt.Println(err)
}
},
}

// ParsePK parses a public key
func ParsePK(_ *pflag.FlagSet, _, v string) cipher.PubKey {
var pk cipher.PubKey
err := pk.Set(v)
if err != nil {
//PrintFatalError(cmdFlags, fmt.Errorf("failed to parse <%s>: %v", name, err))
fmt.Printf("Error")
}
return pk
}
109 changes: 109 additions & 0 deletions cmd/apps/skychat/cli/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Package cli contains code for the cli service of inputports
package cli

import (
"fmt"
"log"

cc "github.com/ivanpirog/coloredcobra"
"github.com/spf13/cobra"

"github.com/skycoin/skywire-utilities/pkg/buildinfo"

clichat "github.com/skycoin/skywire/cmd/apps/skychat/cli/chat"
"github.com/skycoin/skywire/cmd/apps/skychat/internal/app"
"github.com/skycoin/skywire/cmd/apps/skychat/internal/inputports"
"github.com/skycoin/skywire/cmd/apps/skychat/internal/interfaceadapters"
)

var httpport string
var rpcport string

// RootCmd is the root command for skychat
var RootCmd = &cobra.Command{
Use: "skychat",
Short: "skywire chat application",
Long: `
┌─┐┬┌─┬ ┬┌─┐┬ ┬┌─┐┌┬┐
└─┐├┴┐└┬┘│ ├─┤├─┤ │
└─┘┴ ┴ ┴ └─┘┴ ┴┴ ┴ ┴ `,
SilenceErrors: true,
SilenceUsage: true,
DisableSuggestions: true,
DisableFlagsInUseLine: true,
Version: buildinfo.Version(),
Run: func(cmd *cobra.Command, args []string) {

//TODO: Setup Databases depending on flags/attributes

interfaceadapters.InterfaceAdapterServices = interfaceadapters.NewServices()
defer func() {
err := interfaceadapters.InterfaceAdapterServices.Close()
if err != nil {
fmt.Println(err.Error())
}
}()

app.AppServices = app.NewServices(
interfaceadapters.InterfaceAdapterServices.UserRepository,
interfaceadapters.InterfaceAdapterServices.VisorRepository,
interfaceadapters.InterfaceAdapterServices.NotificationService,
interfaceadapters.InterfaceAdapterServices.MessengerService)

inputports.InputportsServices = inputports.NewServices(app.AppServices, httpport, rpcport)

//connectionHandlerService listen
go interfaceadapters.InterfaceAdapterServices.ConnectionHandlerService.Listen()

//rpc-server for cli functionality
go inputports.InputportsServices.RPCServer.ListenAndServe()

//http-server for web-ui
inputports.InputportsServices.HTTPServer.ListenAndServe()
},
}

func init() {
RootCmd.AddCommand(
clichat.RootCmd,
)
var helpflag bool
RootCmd.SetUsageTemplate(help)
RootCmd.PersistentFlags().BoolVarP(&helpflag, "help", "h", false, "help for "+RootCmd.Use)
RootCmd.SetHelpCommand(&cobra.Command{Hidden: true})
RootCmd.PersistentFlags().MarkHidden("help") //nolint

RootCmd.Flags().StringVar(&httpport, "httpport", ":8001", "port to bind")
RootCmd.Flags().StringVar(&rpcport, "rpcport", ":4040", "port to bind")
}

// Execute executes root CLI command.
func Execute() {
cc.Init(&cc.Config{
RootCmd: RootCmd,
Headings: cc.HiBlue + cc.Bold, //+ cc.Underline,
Commands: cc.HiBlue + cc.Bold,
CmdShortDescr: cc.HiBlue,
Example: cc.HiBlue + cc.Italic,
ExecName: cc.HiBlue + cc.Bold,
Flags: cc.HiBlue + cc.Bold,
//FlagsDataType: cc.HiBlue,
FlagsDescr: cc.HiBlue,
NoExtraNewlines: true,
NoBottomNewline: true,
})

if err := RootCmd.Execute(); err != nil {
log.Fatal("Failed to execute command: ", err)
}
}

const help = "Usage:\r\n" +
" {{.UseLine}}{{if .HasAvailableSubCommands}}{{end}} {{if gt (len .Aliases) 0}}\r\n\r\n" +
"{{.NameAndAliases}}{{end}}{{if .HasAvailableSubCommands}}\r\n\r\n" +
"Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand)}}\r\n " +
"{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}\r\n\r\n" +
"Flags:\r\n" +
"{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}\r\n\r\n" +
"Global Flags:\r\n" +
"{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}\r\n\r\n"
Loading

0 comments on commit 4c200f6

Please sign in to comment.