Alteracoes_Samuel
Paulo Simão 2021-09-29 21:00:49 -03:00
commit fdb5553bd7
20 changed files with 1584 additions and 0 deletions

2
.gitignore vendored 100644
View File

@ -0,0 +1,2 @@
.idea
.vscode

2
README.md 100644
View File

@ -0,0 +1,2 @@
# go-client
Core Implementation for Go based Replay features

View File

@ -0,0 +1,48 @@
package anticaptcha
import (
"go.digitalcircle.com.br/open/replaycli-go/api"
)
type Cli struct {
cli *api.Cli
}
func (c *Cli) HttpCli() *api.Cli {
return c.cli
}
type Req struct {
Site string `json:"site"`
Data string `json:"data"`
Img []byte `json:"img"`
To int `json:"to"`
}
func (c *Cli) Recaptchav2(site string, data string) (string, error) {
ret := ""
req := &Req{
Site: site,
Data: data,
Img: nil,
To: 300,
}
err := c.cli.HttpJsonPost("/ipc/anticaptcha/recaptchav2", req, &ret)
return ret, err
}
func (c *Cli) Image2text(site string, data []byte) (string, error) {
ret := ""
req := &Req{
Site: site,
Img: data,
To: 300,
}
err := c.cli.HttpJsonPost("/ipc/anticaptcha/image2text", req, &ret)
return ret, err
}
func NewCli() *Cli {
ret := &Cli{cli: api.NewCli()}
return ret
}

65
api/chrome/cli.go 100644
View File

@ -0,0 +1,65 @@
package chrome
import (
"encoding/json"
"fmt"
"go.digitalcircle.com.br/open/replaycli-go/api"
)
type Cli struct {
cli *api.Cli
}
func (c *Cli) HttpCli() *api.Cli {
return c.cli
}
func (c *Cli) Start(to int) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/chrome/start?to=%d", to), nil)
return err
}
func (c *Cli) StartHeadless() error {
err := c.cli.HttpJsonGet("/ipc/chrome/startHeadless", nil)
return err
}
func (c *Cli) Stop() error {
err := c.cli.HttpJsonGet("/ipc/chrome/stop", nil)
return err
}
func (c *Cli) New(url string) (string, error) {
ret := ""
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/chrome/new?url=%s", url), &ret)
return ret, err
}
func (c *Cli) Close(id string) error {
err := c.cli.HttpJsonGet("/ipc/chrome/close/"+id, nil)
return err
}
func (c *Cli) Eval(id string, s string) (map[string]interface{}, error) {
ret := make(map[string]interface{})
bs, err := c.cli.HttpRawPost("/ipc/chrome/eval/"+id, []byte(s))
json.Unmarshal(bs, &ret)
return ret, err
}
func (c *Cli) Wait(id string, s string, to int) (string, error) {
ret := ""
bs, err := c.cli.HttpRawPost(fmt.Sprintf("/ipc/chrome/wait/%s?to=%d", id, to), []byte(s))
json.Unmarshal(bs, &ret)
return ret, err
}
func (c *Cli) Send(id string, m string, ps map[string]interface{}) (string, error) {
ret := ""
in := map[string]interface{}{
"method": m,
"params": ps,
}
err := c.cli.HttpJsonPost("/ipc/chrome/eval/"+id, in, &ret)
return ret, err
}
func NewCli() *Cli {
ret := &Cli{cli: api.NewCli()}
return ret
}

144
api/cli.go 100644
View File

@ -0,0 +1,144 @@
package api
import (
"bytes"
"encoding/json"
"io"
"net/http"
"os"
"strings"
)
type Cli struct {
cli *http.Client
headers map[string]string
}
func (c *Cli) Addr() string {
ret := os.Getenv("REPLAY_ADDR")
if ret == "" {
ret = "https://localhost:8443"
} else if strings.HasPrefix(ret, ":") {
ret = "https://localhost" + ret
}
return ret
}
func (c *Cli) AddHeader(k string, v string) {
c.headers[k] = v
}
func (c *Cli) DelHeader(k string) {
delete(c.headers, k)
}
func (c *Cli) HttpDo(method string, strurl string, body []byte) (*http.Response, error) {
if !strings.HasPrefix(strurl, "http") {
addr := c.Addr()
if strings.HasSuffix(addr, "/") {
addr = addr[:len(addr)-1]
}
if !strings.HasPrefix(strurl, "") {
strurl = "/" + strurl
}
strurl = addr + strurl
}
req, err := http.NewRequest(method, strurl, bytes.NewReader(body))
if err != nil {
return nil, err
}
if c.headers != nil {
for k, v := range c.headers {
req.Header.Set(k, v)
}
}
if body != nil && len(body) > 0 {
req, err = http.NewRequest(method, strurl, io.NopCloser(bytes.NewReader(body)))
} else {
req, err = http.NewRequest(method, strurl, nil)
}
if err != nil {
return nil, err
}
req.Header.Set("X-API-KEY", apikey)
req.Header.Set("Content-Type", "application/json")
return c.cli.Do(req)
}
func (c *Cli) HttpDoJson(method string, strurl string, i interface{}, o interface{}) (err error) {
bs, err := json.Marshal(i)
if err != nil {
return err
}
res, err := c.HttpDo(method, strurl, bs)
if err != nil {
return
}
defer res.Body.Close()
if o != nil {
err = json.NewDecoder(res.Body).Decode(o)
}
return
}
func (c *Cli) HttpJsonGet(strurl string, o interface{}) error {
return c.HttpDoJson(http.MethodGet, strurl, nil, o)
}
func (c *Cli) HttpJsonDelete(strurl string, o interface{}) error {
return c.HttpDoJson(http.MethodDelete, strurl, nil, o)
}
func (c *Cli) HttpJsonHead(strurl string, o interface{}) error {
return c.HttpDoJson(http.MethodHead, strurl, nil, o)
}
func (c *Cli) HttpJsonPost(strurl string, i interface{}, o interface{}) error {
return c.HttpDoJson(http.MethodPost, strurl, i, o)
}
func (c *Cli) HttpJsonPut(strurl string, i interface{}, o interface{}) error {
return c.HttpDoJson(http.MethodPut, strurl, i, o)
}
func (c *Cli) HttpJsonPatch(strurl string, i interface{}, o interface{}) error {
return c.HttpDoJson(http.MethodPatch, strurl, i, o)
}
func (c *Cli) HttpRawGet(strurl string) ([]byte, error) {
res, err := c.HttpDo(http.MethodGet, strurl, nil)
if err != nil {
return nil, err
}
defer res.Body.Close()
bs, _ := io.ReadAll(res.Body)
return bs, nil
}
func (c *Cli) HttpRawDelete(strurl string) ([]byte, error) {
res, err := c.HttpDo(http.MethodDelete, strurl, nil)
if err != nil {
return nil, err
}
defer res.Body.Close()
bs, _ := io.ReadAll(res.Body)
return bs, nil
}
func (c *Cli) HttpRawPost(strurl string, i []byte) ([]byte, error) {
res, err := c.HttpDo(http.MethodPost, strurl, i)
if err != nil {
return nil, err
}
defer res.Body.Close()
bs, _ := io.ReadAll(res.Body)
return bs, nil
}
func (c *Cli) HttpRawPut(strurl string, i []byte) ([]byte, error) {
res, err := c.HttpDo(http.MethodPut, strurl, i)
if err != nil {
return nil, err
}
defer res.Body.Close()
bs, _ := io.ReadAll(res.Body)
return bs, nil
}
func NewCli() *Cli {
apikey = os.Getenv("REPLAY_APIKEY")
ret := &Cli{
cli: &http.Client{},
headers: make(map[string]string),
}
ret.AddHeader("X-API-KEY", apikey)
return ret
}

64
api/excel/cli.go 100644
View File

@ -0,0 +1,64 @@
package excel
import (
"go.digitalcircle.com.br/open/replaycli-go/api"
)
const (
CELLTYPE_STRING = "s"
CELLTYPE_INT = "i"
CELLTYPE_BOOL = "b"
)
type Cli struct {
cli *api.Cli
}
func (c *Cli) HttpCli() *api.Cli {
return c.cli
}
type Req struct {
File string `json:"file"`
Sheet string `json:"sheet"`
Cel string `json:"cel"`
Val string `json:"val"`
Celtype string `json:"celtype"`
}
func (c *Cli) Read(fname string, sheet string) ([][]string, error) {
req := &Req{
File: fname,
Sheet: sheet,
}
res := make([][]string, 0)
err := c.cli.HttpJsonPost("/ipc/excel/read", req, &res)
return res, err
}
func (c *Cli) Write(fname string, sheet string, cell string, val string, celtype string) error {
req := &Req{
File: fname,
Sheet: sheet,
Cel: cell,
Val: val,
Celtype: celtype,
}
res := ""
err := c.cli.HttpJsonPost("/ipc/excel/write", req, &res)
return err
}
func (c *Cli) New(fname string, sheet string) (string, error) {
req := &Req{
File: fname,
Sheet: sheet,
}
res := ""
err := c.cli.HttpJsonPost("/ipc/excel/new", req, &res)
return res, err
}
func NewCli() *Cli {
ret := &Cli{cli: api.NewCli()}
return ret
}

101
api/lib.go 100644
View File

@ -0,0 +1,101 @@
package api
import (
"bytes"
"encoding/json"
"fmt"
"go.digitalcircle.com.br/open/replaycli-go/types"
"io"
"net/http"
"os"
"strings"
)
var apikey string
func init() {
apikey = os.Getenv("REPLAY_APIKEY")
}
func Addr() string {
ret := os.Getenv("REPLAY_ADDR")
if ret == "" {
ret = "http://localhost:8080"
} else if strings.HasPrefix(ret, ":") {
ret = "http://localhost" + ret
}
return ret
}
func HttpDo(method string, strurl string, body []byte) (*http.Response, error) {
cli := http.Client{}
var err error
var req *http.Request
if body != nil && len(body) > 0 {
req, err = http.NewRequest(method, strurl, io.NopCloser(bytes.NewReader(body)))
} else {
req, err = http.NewRequest(method, strurl, nil)
}
if err != nil {
return nil, err
}
req.Header.Set("X-API-KEY", apikey)
req.Header.Set("Content-Type", "application/json")
return cli.Do(req)
}
func HttpDoJson(i interface{}, method string, strurl string, body []byte) (err error) {
res, err := HttpDo(method, strurl, body)
if err != nil {
return
}
err = json.NewDecoder(res.Body).Decode(i)
return
}
type roboDAO struct {
}
func (d roboDAO) GetAll() ([]*types.Robot, error) {
ret := make([]*types.Robot, 0)
err := HttpDoJson(&ret, http.MethodGet, Addr()+fmt.Sprintf("/api/v1/robots"), nil)
return ret, err
}
func (d roboDAO) Enqueue(id uint) error {
_, err := HttpDo(http.MethodGet, Addr()+fmt.Sprintf("/api/v1/robots/op/enqueue/%d", id), nil)
return err
}
var RoboDAO roboDAO
type sqlDAO struct {
}
func (d sqlDAO) SQL(s string) (types.SQLResponse, error) {
ret := types.SQLResponse{}
req := types.SQLRequest{Sql: s}
bs, _ := json.Marshal(req)
err := HttpDoJson(&ret, http.MethodPost, Addr()+fmt.Sprintf("/api/v1/sql"), bs)
return ret, err
}
var SQLDAO sqlDAO
type appDAO struct {
}
func (d appDAO) GetAll() ([]*types.App, error) {
ret := make([]*types.App, 0)
err := HttpDoJson(&ret, http.MethodGet, Addr()+fmt.Sprintf("/api/v1/apps"), nil)
return ret, err
}
func (d appDAO) Run(id interface{}) ([]*types.App, error) {
ret := make([]*types.App, 0)
err := HttpDoJson(&ret, http.MethodGet, Addr()+fmt.Sprintf("/api/v1/app/run/%v", id), nil)
return ret, err
}
var AppDAO appDAO

89
api/replay/cli.go 100644
View File

@ -0,0 +1,89 @@
package replay
import (
"fmt"
"os"
"go.digitalcircle.com.br/open/replaycli-go/api"
"go.digitalcircle.com.br/open/replaycli-go/types"
"go.digitalcircle.com.br/open/replaycli-go/util"
)
type Cli struct {
cli *api.Cli
}
func (c *Cli) HttpCli() *api.Cli {
return c.cli
}
func (c *Cli) OpenApp(id uint) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/api/v1/app/run/%d", id), nil)
return err
}
func (c *Cli) ConfigGet(k string) (ret string, err error) {
err = c.cli.HttpJsonGet("/api/v1/config/byrepo/"+util.Repo()+"/"+k, &ret)
return
}
func (c *Cli) ConfigGetAll() (ret []types.Config, err error) {
ret = make([]types.Config, 0)
err = c.cli.HttpJsonGet("/api/v1/config/byrepo/"+util.Repo(), &ret)
return
}
func (c *Cli) CronReload() error {
return c.cli.HttpJsonGet("/ipc/cron/reload", nil)
}
func (c *Cli) Exit() error {
err := c.cli.HttpJsonGet("/api/v1/exit", nil)
return err
}
func (c *Cli) MenuGetAllEnabled() (ret []types.Menu, err error) {
ret = make([]types.Menu, 0)
err = c.cli.HttpJsonGet("/api/v1/menu/enabled", nil)
return ret, err
}
func (c *Cli) QueueAdd(job string, bs []byte) error {
return c.cli.HttpJsonGet("/api/v1/queue/add/"+job, bs)
}
func (c *Cli) QueueGetData(id string) (ret []byte, err error) {
ret, err = c.cli.HttpRawGet("/api/v1/queue/getrequest/" + id)
return
}
func (c *Cli) QueueGetMyData() ([]byte, error) {
return c.QueueGetData(os.Getenv("REPLAY_QUEUEID"))
}
func (c *Cli) QueueAbort() error {
return c.cli.HttpJsonGet("/api/v1/queue/abort", nil)
}
func (c *Cli) QueueEnqueue(id uint) error {
return c.cli.HttpJsonGet(fmt.Sprintf("/api/v1/robots/op/enqueue/%d", id), nil)
}
func (c *Cli) ServiceStopAll() error {
return c.cli.HttpJsonGet("/api/v1/service/op/stopall", nil)
}
type SQLReturn struct {
Data []map[string]interface{} `json:"data"`
Err string `json:"err"`
}
func (c *Cli) SQL(s string) (*SQLReturn, error) {
in := &struct {
Sql string `json:"sql"`
}{s}
out := &SQLReturn{}
err := c.cli.HttpJsonPost("/api/v1/sql", in, &out)
return out, err
}
func NewCli() *Cli {
ret := &Cli{cli: api.NewCli()}
return ret
}

80
api/wingui/cli.go 100644
View File

@ -0,0 +1,80 @@
package wingui
import (
"fmt"
"go.digitalcircle.com.br/open/replaycli-go/api"
)
type Cli struct {
cli *api.Cli
}
func (c *Cli) HttpCli() *api.Cli {
return c.cli
}
func (c *Cli) ClipRead() (string, error) {
ret := ""
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/clip/read"), &ret)
return ret, err
}
func (c *Cli) ClipWrite(site string) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/clip/write?str=%s", site), nil)
return err
}
func (c *Cli) MouseClick() error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/mouse/click"), nil)
return err
}
func (c *Cli) MouseMove(x, y int) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/mouse/move?x=%d&y=%d", x, y), nil)
return err
}
func (c *Cli) MouseMoveRelative(x, y int) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/mouse/moverelative?x=%d&y=%d", x, y), nil)
return err
}
func (c *Cli) MouseClickRelative(x, y int) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/mouse/clickatrelative?x=%d&y=%d", x, y), nil)
return err
}
func (c *Cli) MouseClickAt(x, y int) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/mouse/clickat?x=%d&y=%d", x, y), nil)
return err
}
func (c *Cli) ScreenClick(f string) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/screen/click?f=%s", f), nil)
return err
}
func (c *Cli) ScreenClickCenter(f string) error {
err := c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/screen/clickcenter?f=%s", f), nil)
return err
}
func (c *Cli) ScreenFind(f string) (ret map[string]interface{}, err error) {
ret = make(map[string]interface{})
err = c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/screen/find?f=%s", f), &ret)
return
}
func (c *Cli) ScreenWait(f string, m int) (ret map[string]interface{}, err error) {
ret = make(map[string]interface{})
err = c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/screen/wait?f=%s&m=%d", f, m), &ret)
return
}
func (c *Cli) ScreenWaitClick(f string, m int) (ret map[string]interface{}, err error) {
ret = make(map[string]interface{})
err = c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/screen/waitclick?f=%s&m=%d", f, m), &ret)
return
}
func (c *Cli) ScreenWaitClickCenter(f string, m int) (ret map[string]interface{}, err error) {
ret = make(map[string]interface{})
err = c.cli.HttpJsonGet(fmt.Sprintf("/ipc/wingui/screen/waitclickcenter?f=%s&m=%d", f, m), &ret)
return
}
func NewCli() *Cli {
ret := &Cli{cli: api.NewCli()}
return ret
}

78
constants/lib.go 100644
View File

@ -0,0 +1,78 @@
package constants
const (
FEATURE_ROBOT = "robot"
FEATURE_SERVICE = "service"
FEATURE_APP = "app"
FEATURE_RUNTIME = "runtime"
RUNNER_BIN = "bin"
RUNNER_PYTHON = "python"
RUNNER_SHELL = "shell"
ENV_ROOT = "ROOT"
ENV_IPC = "IPC"
ENV_ROOTPID = "ROOT_PID"
ENV_ADDR = "ADDR"
ENV_LISTEN_ADDR = "LISTENADDR"
ENV_DUMPENV = "DUMPENV"
ENV_IPC_TCP = "IPC_TCP"
ENV_LOG = "LOG"
ENV_DEBUG_PROTO = "DEBUG_PROTO"
ENV_PYTHON = "PYTHON"
ENV_HTTPBASE = "HTTPBASE"
ENV_STRAWID = "STRAWID"
IPC_CORE = "core"
IPC_SVC_CLIP = "clip"
IPC_STATIC = "static"
IPC_DB = "db"
IPC_NOTIFY = "notify"
IPC_CORE_reg = "reg"
IPC_CORE_regs = "regs"
IPC_CORE_unreg = "unreg"
IPC_CORE_db_ConfigGet = "db.ConfigGet"
IPC_CORE_db_MenuGet = "db.MenuGet"
IPC_CORE_db_QueueAdd = "db.QueueAdd"
BASE_URL = "BASE_URL"
ADDR = "ADDR"
PYTHON = "PYTHON"
SHELL = "SHELL"
ROOT = "ROOT"
LOGGING = "LOGGING"
RESTART = "RESTART"
CHECK_URL = "CHECK_URL"
ROBOT_ID = "ROBOT_ID"
OWNER = "OWNER"
SHOWCONSOLE = "SHOWCONSOLE"
UID = "UID"
VSCODE = "VSCODE"
SCRIPTS_ROOT = "SCRIPTS_ROOT"
REPOS_ROOT = "REPOS_ROOT"
STATIC_ROOT = "STATIC_ROOT"
AUTO_OPEN_CONSOLE = "AUTO_OPEN_CONSOLE"
NOTIFY_ON_OPEN = "NOTIFY_ON_OPEN"
USE_TRAY = "USE_TRAY"
TEMP = "TEMP"
WORKINGIR = "WORKINGIR"
ADDONS_DIR = "ADDONS_DIR"
CHANNEL = "CHANNEL"
API_VERCHECK = "/api/vercheck"
API_VERGET = "/api/verget"
EVT_TYPE_JOBSTART = "jobstart"
EVT_TYPE_JOBFINISH = "jobfinish"
EVT_TYPE_APPSTART = "appstart"
EVT_TYPE_APPFINISH = "appfinish"
ENV_REPLAY_INSTANCE_ALIAS = "REPLAY_INSTANCE_ALIAS"
ENV_ROOT_PID = "ROOT_PID"
ENV_REPLAY_ADDR = "REPLAY_ADDR"
ENV_REPLAY_DATADIR = "REPLAY_DATADIR"
ENV_REPLAY_REPO = "REPLAY_REPO"
ENV_REPLAY_APIKEY = "REPLAY_APIKEY"
ENV_REPLAY_ALIAS = "REPLAY_ALIAS"
ENV_REPLAY_VER = "REPLAY_VER"
ENV_REPLAY_QUEUEID = "REPLAY_QUEUEID"
)

11
errmgr/lib.go 100644
View File

@ -0,0 +1,11 @@
package errmgr
import "log"
func Report(err error) bool {
if err != nil {
log.Printf(err.Error())
return true
}
return false
}

10
go.mod 100644
View File

@ -0,0 +1,10 @@
module go.digitalcircle.com.br/open/replaycli-go
go 1.17
require (
github.com/Microsoft/go-winio v0.5.0
github.com/gorilla/websocket v1.4.2
github.com/mitchellh/go-ps v1.0.0
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
)

17
go.sum 100644
View File

@ -0,0 +1,17 @@
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210921065528-437939a70204 h1:JJhkWtBuTQKyz2bd5WG9H8iUsJRU3En/KRfN8B2RnDs=
golang.org/x/sys v0.0.0-20210921065528-437939a70204/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

94
ipcmux/lib.go 100644
View File

@ -0,0 +1,94 @@
package ipcmux
import (
"context"
"log"
"net"
"net/http"
"os"
"runtime"
"strings"
)
const (
ENV_IPC = "IPC"
ENV_ROOTPID = "ROOT_PID"
)
var listenNet func(path string) (net.Listener, error)
var dialNet func(path string) (net.Conn, error)
func Dial(p string) (net.Conn, error) {
return dialNet(p)
}
func SetName(n string) {
os.Setenv(ENV_IPC, n)
}
func ResolveBinName() string {
bin := os.Getenv(ENV_IPC)
if bin == "" {
bin = os.Args[0]
if runtime.GOOS == "windows" {
bin = strings.Replace(bin, "\\", "/", -1)
}
parts := strings.Split(bin, "/")
bin = parts[len(parts)-1]
bin = strings.Replace(bin, ".exe", "", 1)
log.Printf("No IPC env var found, using %s to bind ipc", bin)
}
return bin
}
func Listen(p string) (net.Listener, error) {
log.Printf("IPC:: Will listen on: [%s]", p)
return listenNet(p)
}
func NewClient() *http.Client {
ret := &http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, b string) (net.Conn, error) {
ps := strings.Split(b, ":")
return dialNet(ps[0])
},
},
}
return ret
}
func Serve(mux *http.ServeMux) error {
go CheckRoot()
bin := ResolveBinName()
l, err := Listen(bin)
if err != nil {
return err
}
server := http.Server{
Handler: mux,
}
err = server.Serve(l)
return err
}
func ServeNamed(n string, mux *http.ServeMux) error {
go CheckRoot()
l, err := Listen(n)
if err != nil {
return err
}
server := http.Server{
Handler: mux,
}
err = server.Serve(l)
return err
}
func ServeDefault() error {
return Serve(http.DefaultServeMux)
}

76
ipcmux/lib_unix.go 100644
View File

@ -0,0 +1,76 @@
//go:build !windows
// +build !windows
package ipcmux
import (
"github.com/mitchellh/go-ps"
"log"
"net"
"os"
libpath "path"
"strconv"
"time"
)
func init() {
listenNet = func(path string) (net.Listener, error) {
ipc_root := os.Getenv("IPC_ROOT")
if ipc_root == "" {
ipc_root = os.TempDir()
}
path = "replayme_" + path
path = libpath.Join(ipc_root, path)
err := os.Remove(path)
if err != nil {
if !os.IsNotExist(err) {
log.Printf("Err removing old uds: %s", err.Error())
}
}
l, err := net.Listen("unix", path)
log.Printf("UnixSocket::%s=>%v", path, err)
return l, err
}
dialNet = func(path string) (net.Conn, error) {
ipc_root := os.Getenv("IPC_ROOT")
if ipc_root == "" {
ipc_root = os.TempDir()
}
path = "replayme_" + path
path = libpath.Join(ipc_root, path)
conn, err := net.Dial("unix", path)
return conn, err
}
}
const (
PRCTL_SYSCALL = 157
PR_SET_PDEATHSIG = 1
)
func CheckRoot() {
time.Sleep(time.Second)
rootpid := os.Getenv(ENV_ROOTPID)
rootpidi, err := strconv.Atoi(rootpid)
if err != nil {
log.Printf("No root process found")
return
}
if rootpidi == 0 || rootpidi == os.Getpid() {
log.Printf("%s is set to zero, no monitoring on root will take place", ENV_ROOTPID)
return
}
for {
p, err := ps.FindProcess(rootpidi)
if p == nil || err != nil {
log.Printf("aborting")
os.Exit(1)
}
time.Sleep(time.Second)
}
}

View File

@ -0,0 +1,116 @@
//go:build windows
// +build windows
package ipcmux
import (
"errors"
"github.com/Microsoft/go-winio"
"log"
"net"
"os"
"strconv"
"strings"
"time"
)
func init() {
listenNet = func(path string) (net.Listener, error) {
path = strings.Replace(path, "/", "\\", -1)
log.Printf("Listening to: " + path)
chcon := make(chan bool)
var conn net.Listener
var err error
go func() {
path = "\\\\.\\pipe\\" + path
conn, err = winio.ListenPipe(path, &winio.PipeConfig{
SecurityDescriptor: "",
MessageMode: false,
InputBufferSize: 0,
OutputBufferSize: 0,
})
if err != nil {
log.Printf("ipcmux::listenNet: %s", err.Error())
}
go func() {
go func() {
to := time.Second * time.Duration(3)
fconn, err := winio.DialPipe(path, &to)
if err != nil {
log.Printf("Error on pipe warm up: %s", err.Error())
} else {
fconn.Close()
}
log.Printf("Pipe warm up done")
}()
}()
chcon <- true
}()
select {
case <-chcon:
return conn, err
case <-time.After(time.Second * 5):
err = errors.New("Timeout exceeded for Listening: " + path)
return nil, err
}
return conn, err
}
dialNet = func(path string) (net.Conn, error) {
path = strings.Replace(path, "/", "\\", -1)
path = "\\\\.\\pipe\\" + path
chcon := make(chan bool)
var conn net.Conn
var err error
//Log("Dialing to: " + path)
go func() {
to := time.Second * time.Duration(15)
conn, err = winio.DialPipe(path, &to)
//conn, err = npipe.Dial(path)
chcon <- true
}()
select {
case <-chcon:
return conn, err
case <-time.After(time.Second * 5):
err = errors.New("Timeout exceeded for conn: " + path)
return nil, err
}
return conn, err
}
}
func CheckRoot() {
time.Sleep(time.Second)
rootpid := os.Getenv(ENV_ROOTPID)
rootpidi, err := strconv.Atoi(rootpid)
if err != nil {
log.Printf("No root process found")
}
if rootpidi == 0 || rootpidi == os.Getpid() {
log.Printf("%s is set to zero, no monitoring on root will take place", ENV_ROOTPID)
return
}
p, err := os.FindProcess(rootpidi)
if err != nil {
log.Printf("Error finding process: %s", err.Error())
os.Exit(1)
}
if p == nil {
log.Printf("Process not found.")
os.Exit(1)
}
_, err = p.Wait()
if err != nil {
log.Printf(err.Error())
}
log.Printf("Parent process %s is gone. Finishing here.", os.Getenv(ENV_ROOTPID))
os.Exit(0)
}

102
pubsub/lib.go 100644
View File

@ -0,0 +1,102 @@
package pubsub
import (
"encoding/json"
"fmt"
"github.com/gorilla/websocket"
"go.digitalcircle.com.br/open/replaycli-go/ipcmux"
"log"
"net"
"os"
"os/user"
"strings"
"time"
)
const XMSGTYPE = "X-MSGTYPE"
const XPUBSUBID = "X-PUBSUBID"
var PSID = ""
var dialer *websocket.Dialer
func init() {
dialer = &websocket.Dialer{}
hname, _ := os.Hostname()
pid := os.Getppid()
u, _ := user.Current()
PSID = fmt.Sprintf("psid_%s_%s_%d", hname, u.Username, pid)
dialer.NetDial = func(network, addr string) (net.Conn, error) {
ps := strings.Split(addr, ":")
c, err := ipcmux.Dial(ps[0])
return c, err
}
}
type PSCli struct {
q string
con *websocket.Conn
ch chan []byte
closed bool
}
func (p *PSCli) GetConn() *websocket.Conn {
if p.con == nil {
var counter = 0
for counter < 100 {
con, _, err := dialer.Dial("ws://pubsub/?q="+p.q, nil)
if err != nil {
log.Printf("Error connecting WS: %s", err.Error())
counter++
time.Sleep(time.Second)
continue
}
p.con = con
p.con.SetCloseHandler(func(code int, text string) error {
log.Printf("Connection closed: %d: %s", code, text)
p.con = nil
return nil
})
break
}
}
return p.con
}
func (p *PSCli) Send(i interface{}) error {
bs, err := json.Marshal(i)
if err != nil {
return err
}
err = p.GetConn().WriteMessage(websocket.TextMessage, bs)
if err != nil {
p.con.Close()
p.con = nil
}
return err
}
func (p *PSCli) Chan() chan []byte {
return p.ch
}
func (p *PSCli) Read(i interface{}) error {
_, bs, err := p.GetConn().ReadMessage()
if err != nil {
if p.con != nil {
p.con.Close()
p.con = nil
}
return err
}
return json.Unmarshal(bs, i)
}
func NewCli(q string) (*PSCli, error) {
ret := &PSCli{}
ret.q = q
return ret, nil
}

66
static/static.go 100644
View File

@ -0,0 +1,66 @@
package static
import (
"flag"
"go.digitalcircle.com.br/open/replaycli-go/ipcmux"
"mime"
"net/http"
"os"
"path/filepath"
"strings"
)
var builtinMimeTypesLower = map[string]string{
".css": "text/css; charset=utf-8",
".gif": "image/gif",
".htm": "text/html; charset=utf-8",
".html": "text/html; charset=utf-8",
".jpg": "image/jpeg",
".js": "application/javascript",
".wasm": "application/wasm",
".pdf": "application/pdf",
".png": "image/png",
".svg": "image/svg+xml",
".xml": "text/xml; charset=utf-8",
}
func Mime(ext string) string {
if v, ok := builtinMimeTypesLower[ext]; ok {
return v
}
return mime.TypeByExtension(ext)
}
func ServeParse() {
addr := flag.String("ipc", "samplestatic", "IPC Addr")
root := flag.String("root", ".", "Root dir")
flag.Parse()
Serve(*addr, *root)
}
func Serve(addr string, root string) {
ipcmux.SetName(addr)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
path := strings.Split(r.URL.Path, "?")[0]
if path == "" {
path = "index.html"
}
ext := filepath.Ext(path)
bs, err := os.ReadFile(filepath.Join(root, path))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Header().Set("Content-Type", Mime(ext))
w.Write(bs)
})
ipcmux.ServeDefault()
}

349
types/lib.go 100644
View File

@ -0,0 +1,349 @@
package types
import (
"time"
)
//region AUTH
type SecUser struct {
Model
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
Groups []*SecGroup `json:"groups" gorm:"many2many:sec_user_groups;"`
}
type SecGroup struct {
Model
Code string `json:"code"`
Name string `json:"name"`
//Users []*SecUser `json:"users" gorm:"many2many:sec_user_groups;"`
Perms []*SecPerm `json:"perms" gorm:"many2many:sec_group_perms;"`
}
type SecPerm struct {
Model
Code string `json:"code"`
Name string `json:"name"`
Value string `json:"value"`
//Groups []*SecGroup `json:"groups" gorm:"many2many:group_perms;"`
}
type Session struct {
Model
Username string
SessionID string
Perms string
}
//endregion AUTH
type Feature struct {
Model
Name string `json:"name" yaml:"name"`
Desc string `json:"desc" yaml:"desc"`
Repo uint `json:"repo"`
Alias string `json:"alias"`
}
type Robot struct {
Feature
}
type App struct {
Feature
IsNative *bool
}
type Service struct {
Feature
Ipcid string `json:"ipcid"`
Env string `json:"env" yaml:"env"`
Enabled *bool `yaml:"enabled" json:"enabled"`
Image string `yaml:"image" json:"image"`
Delay int `yaml:"delay" json:"delay"`
Pid int `json:"pid" yaml:"-"`
Hostname string `json:"hostname" yaml:"hostname"`
Gui bool `json:"gui" yaml:"gui"`
}
type Runtime struct {
Feature
Path string `json:"path" yaml:"path"`
}
type Repo struct {
Model
Feature string `json:"feature" yaml:"feature"`
Name string `json:"name" yaml:"name"`
Url string `json:"repo"`
Alias string `json:"alias"`
Cred uint `json:"cred"`
LocalDir string `json:"local_dir"`
Status string `json:"status"`
}
type ReplayDescriptor struct {
Feature string `json:"feature" yaml:"feature"`
ReplayID string `json:"replay_id" yaml:"replay_id"`
Name string `json:"name" yaml:"name"`
Desc string `json:"desc" yaml:"desc"`
Runner string `json:"runner" yaml:"runner"`
Main string `json:"main" yaml:"main"`
Args []string `json:"args" yaml:"args"`
Env map[string]string `json:"env" yaml:"env"`
InstallScript string `json:"install_script" yaml:"install_script"`
UninstallScript string `json:"uninstall_script" yaml:"uninstall_script"`
AbortScript string `json:"abort_script" yaml:"abort_script"`
Id string `json:"id" yaml:"-"`
LocalDir string `json:"local_dir" yaml:"-"`
RepoID uint `json:"repo_id" yaml:"-"`
QueueID uint `json:"queue_id" yaml:"-"`
Config map[string]string `json:"config" yaml:"config"`
Alias string `json:"alias" yaml:"alias"`
Autostart bool `json:"autostart" yaml:"autostart"`
Hostname string `json:"hostname" yaml:"hostname"`
Ipcid string `json:"ipcid"`
Gui bool `json:"gui" yaml:"gui"`
Link string `json:"link" yaml:"link"` //This prop allows redirect of repos
}
type NotifyRequest struct {
Title string
Msg string
}
type Model struct {
ID uint `gorm:"primarykey" json:"id"`
}
//type Model simpledb.SimplePersistent
type Menu struct {
Model
Name string `json:"name"`
Label string `json:"label"`
Tooltip string `json:"tooltip"`
Target string `json:"target"`
Index int `json:"index" gorm:"column:menuindex"`
Enabled *bool `json:"enabled"`
}
type Config struct {
Model
K string `json:"k"`
V string `json:"v"`
T string `json:"t"`
Repo uint `json:"repo"`
}
type Credentials struct {
Model
Name string `json:"name"`
User string `json:"user"`
Password string `json:"password"`
Sshkey string `json:"sshkey"`
}
type Log struct {
Model
Log []byte
}
type Job struct {
Model
Name string `json:"name"`
Code string `json:"code"`
File string `json:"file"`
Notes string `json:"notes"`
}
type Route struct {
Model
From string `json:"from"`
Host string `json:"host"`
To string `json:"to"`
Desc string `json:"desc"`
Enabled *bool `json:"enabled"`
Index string `json:"index"`
HeadersJson string `json:"headers_json"`
Permissions string `json:"permissions"`
PermArr []string `json:"-" gorm:"-"`
}
type Queue struct {
Model
Job uint `json:"job"`
Ready bool `json:"ready"`
Processed bool `json:"processed"`
ProcessedAt time.Time `json:"processed_at"`
Request []byte
}
//type QueueData struct {
// Model
// Qid uint
// Request []byte
//}
type CryptoKey struct {
Model
Defkey bool
Name string
Pub []byte
Priv []byte
}
type Options struct {
ID string `json:"id"`
Value string `json:"value"`
}
//type Version struct {
// Model
// Job string `json:"job"`
// Ver string `json:"ver"`
// Notes string `json:"notes"`
//}
//
//type VersionData struct {
// Model
// Vid uint `json:"vid"`
// Data []byte `json:"data"`
//}
type Cron struct {
Model
Cron string `json:"cron"`
JobCode uint `json:"job"`
Enabled *bool `json:"enabled"`
}
//type Resource struct {
// Model
// Name string `json:"name"`
// Mime string `json:"mime"`
// Len int `json:"len"`
//}
//
//type ResourceContent struct {
// Model
// Resid uint `json:"resid"`
// Content []byte `json:"content"`
//}
type License struct {
Model
Owner string `json:"owner"`
RobotID string `json:"robot_id"`
MachineID string `json:"machine_id"`
UID string `json:"uid"`
Alias string `json:"alias"`
}
type KV struct {
ID string `gorm:"primarykey" json:"id"`
V string `json:"v"`
}
/*
@API
*/
type VerCheckRequest struct {
Chan string `json:"chan"`
Os string `json:"os"`
Arch string `json:"arch"`
Data map[string]string `json:"data"`
}
/*
@API
*/
type VerCheckResponse struct {
Data map[string]string `json:"data"`
}
/*
@API
*/
type VerGetRequest struct {
Os string `json:"os"`
Chan string `json:"chan"`
Arch string `json:"arch"`
Id string `json:"id"`
}
/*
@API
*/
type VerGetResponse struct {
Data []byte `json:"data"`
}
type SQLRequest struct {
Sql string `json:"sql"`
}
type SQLResponse struct {
Data interface{} `json:"data"`
Err string `json:"err"`
}
type SecUserChOwnPassRequest struct {
Oldpass string `json:"oldpass"`
Newpass string `json:"newpass"`
}
type LoginRequest struct {
Username string
Password string
}
type RecipeItem struct {
Url string `json:"url" yaml:"url"`
User string `json:"user" yaml:"user"`
Password string `json:"password" yaml:"password"`
Sshkey string `json:"sshkey" yaml:"sshkey"`
}
type Recipe struct {
User string `json:"user" yaml:"user"`
Password string `json:"password" yaml:"password"`
Sshkey string `json:"sshkey" yaml:"sshkey"`
LicUser string `json:"licuser" yaml:"licuser"`
License string `json:"license" yaml:"license"`
Alias string `json:"alias" yaml:"alias"`
Items []RecipeItem `json:"items" yaml:"items"`
}
type PubSubMsg struct {
Msg string
Data interface{}
}
type PubSubMsgRunnerFinishData struct {
Err error
Desc *ReplayDescriptor
}
type Series struct {
Serie string `json:"serie"`
When time.Time `json:"when"`
Value float64 `json:"value"`
Sec int `json:"sec"`
Min int `json:"min"`
Hour int `json:"hour"`
Day int `json:"day"`
Month int `json:"month"`
Year int `json:"year"`
}
func (s *Series) SetTime(t time.Time) {
s.When = t
s.Day = t.Day()
s.Hour = t.Hour()
s.Min = t.Minute()
s.Sec = t.Second()
s.Month = int(t.Month())
s.Year = t.Year()
}

70
util/lib.go 100644
View File

@ -0,0 +1,70 @@
package util
import (
"go.digitalcircle.com.br/open/replaycli-go/constants"
"os"
"strings"
)
var apikey string
func init() {
apikey = os.Getenv("REPLAY_APIKEY")
}
func Addr() string {
ret := os.Getenv("REPLAY_ADDR")
if ret == "" {
ret = "http://localhost:8080"
} else if strings.HasPrefix(ret, ":") {
ret = "http://localhost" + ret
}
return ret
}
func DataDir() string {
ret := os.Getenv(constants.ENV_REPLAY_DATADIR)
return ret
}
func Repo() string {
repo := os.Getenv("REPLAY_REPO")
if repo == "" {
path, _ := os.Getwd()
path = strings.Replace(path, "\\", "/", -1)
pathparts := strings.Split(path, "/")
repo = pathparts[len(pathparts)-1]
}
return repo
}
//
//func HttpDo(method string, strurl string, body []byte) (*http.Response, error) {
// cli := http.Client{}
// var err error
// var req *http.Request
//
// if body != nil && len(body) > 0 {
// req, err = http.NewRequest(method, strurl, io.NopCloser(bytes.NewReader(body)))
//
// } else {
// req, err = http.NewRequest(method, strurl, nil)
// }
// if err != nil {
// return nil, err
// }
// req.Header.Set("X-API-KEY", apikey)
// req.Header.Set("Content-Type", "application/json")
// return cli.Do(req)
//}
//
//func HttpDoJson(i interface{}, method string, strurl string, body []byte) (err error) {
// res, err := HttpDo(method, strurl, body)
// if err != nil {
// return
// }
// err = json.NewDecoder(res.Body).Decode(i)
// return
//}