mirror of
https://github.com/donuts-are-good/neosay.git
synced 2025-08-02 11:56:08 -04:00
hello neo...
This commit is contained in:
commit
ab5679805a
6 changed files with 255 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.DS_Store
|
||||||
|
.Trash-1000
|
||||||
|
neosay
|
||||||
|
neosay.json
|
||||||
|
BUILDS
|
81
README.md
Normal file
81
README.md
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
|
||||||
|
  
|
||||||
|
|
||||||
|
# 🎉 Neosay
|
||||||
|
Neosay is an easy CLI tool that allows you to send messages and code from files or stdin to Matrix.
|
||||||
|
|
||||||
|
## 📥 Click the banner to download
|
||||||
|
|
||||||
|
[](https://github.com/donuts-are-good/neosay/releases/latest)
|
||||||
|
|
||||||
|
Download a copy of Neosay for your system by clicking the big green banner above.
|
||||||
|
|
||||||
|
|
||||||
|
## 🚀 Building It Yourself
|
||||||
|
To build Neosay, you'll need to clone the repository and build the binary:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/donuts-are-good/neosay.git
|
||||||
|
cd neosay
|
||||||
|
go build
|
||||||
|
```
|
||||||
|
## 📝 Configuration (Environment Variables)
|
||||||
|
You may want to use Neosay with environment variables instead of a config file.
|
||||||
|
|
||||||
|
```
|
||||||
|
echo "Hello, world!" | ./neosay
|
||||||
|
```
|
||||||
|
|
||||||
|
You can load in your configuration details as environment variables like this in your environment:
|
||||||
|
|
||||||
|
```
|
||||||
|
export MATRIX_HOMESERVER_URL="https://matrix.example.com"
|
||||||
|
export MATRIX_USER_ID="@yourusername:example.com"
|
||||||
|
export MATRIX_ACCESS_TOKEN="your_access_token"
|
||||||
|
export MATRIX_ROOM_ID="!yourroomid:example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 📝 Configuration (JSON)
|
||||||
|
Neosay can optionally use a JSON configuration file to store the Matrix homeserver URL, user ID, access token, and room ID. This makes it easy to switch between rooms.
|
||||||
|
|
||||||
|
**Note:** Be careful using this method, anybody can inmpersonate you with this information. It's best to make a different account for this.
|
||||||
|
|
||||||
|
Here's an example of the JSON configuration file:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"homeserverURL": "https://matrix.example.com",
|
||||||
|
"userID": "@yourusername:example.com",
|
||||||
|
"accessToken": "your_access_token",
|
||||||
|
"roomID": "!yourroomid:example.com"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## 🌟 Examples
|
||||||
|
|
||||||
|
### Sending a simple message
|
||||||
|
`echo "Hello, world!" | ./neosay config.json`
|
||||||
|
|
||||||
|
### Sending a multi-line message
|
||||||
|
`cat yourfile.txt | ./neosay config.json`
|
||||||
|
|
||||||
|
### Sending a code block
|
||||||
|
`echo "Hello, world!" | ./neosay -c config.json`
|
||||||
|
|
||||||
|
### Sending a multi-line code block
|
||||||
|
`cat yourcodefile.py | ./neosay --code config.json`
|
||||||
|
|
||||||
|
## 🤖 Neosay in the wild
|
||||||
|
Here are some other ways to use Neosay:
|
||||||
|
|
||||||
|
- Share code snippets with your team in a Matrix room
|
||||||
|
- Send logs or debugging information from a script
|
||||||
|
- Share inspirational quotes or jokes
|
||||||
|
- Send notifications from your CI/CD pipelines or monitoring tools
|
||||||
|
|
||||||
|
|
||||||
|
## 📡 Contributing
|
||||||
|
I'll take help however you can get it to me, whether that be a pull request, a .patch file, a sticky note, smoke signals, bribes, you name it.
|
||||||
|
|
||||||
|
## 🖇️ License
|
||||||
|
`neosay` is licensed under the MIT license. Check out the LICENSE file for more info. If you dont get it don't worry about it.
|
6
example.json
Normal file
6
example.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"homeserverURL": "https://matrix.org",
|
||||||
|
"userID": "@example:matrix.org",
|
||||||
|
"accessToken": "my_access_token",
|
||||||
|
"roomID": "!oJJwhvLOYfduLjDTjA:matrix.org"
|
||||||
|
}
|
10
go.mod
Normal file
10
go.mod
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
module github.com/donuts-are-good/neosay
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/donuts-are-good/colors v1.1.1
|
||||||
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
||||||
|
)
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.7.0 // indirect
|
6
go.sum
Normal file
6
go.sum
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
github.com/donuts-are-good/colors v1.1.1 h1:1dl9M5B8v+5N8y9iggmyi1QWndCRBbeiknrm8wyiZ6U=
|
||||||
|
github.com/donuts-are-good/colors v1.1.1/go.mod h1:qJm/kwHGeQLrMKWyplA9/IkT9wwOLL3vx0Wlcn7ntPc=
|
||||||
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
|
||||||
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||||
|
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
147
main.go
Normal file
147
main.go
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/donuts-are-good/colors"
|
||||||
|
"github.com/matrix-org/gomatrix"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
HomeserverURL string `json:"homeserverURL"`
|
||||||
|
UserID string `json:"userID"`
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
RoomID string `json:"roomID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxMessageSize = 4000
|
||||||
|
const messageDelay = 2 * time.Second
|
||||||
|
|
||||||
|
var codeFlag bool
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// name the argset
|
||||||
|
args := os.Args[1:]
|
||||||
|
|
||||||
|
// if we get too few, supply the usage
|
||||||
|
if len(args) < 1 {
|
||||||
|
fmt.Fprintln(os.Stderr, colors.BrightRed+"Usage: neosay <config-file> [-c | --code]"+colors.Nc)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// name the config file
|
||||||
|
configFile := args[0]
|
||||||
|
|
||||||
|
// check for the args, which can be anywhere
|
||||||
|
for _, arg := range args[1:] {
|
||||||
|
if arg == "--code" || arg == "-c" {
|
||||||
|
codeFlag = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the config
|
||||||
|
file, err := os.Open(configFile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, colors.BrightRed+"error opening config file:"+colors.Nc, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// load the config into json
|
||||||
|
config := &Config{}
|
||||||
|
decoder := json.NewDecoder(file)
|
||||||
|
if err := decoder.Decode(config); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, colors.BrightRed+"error reading config file:"+colors.Nc, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the homeserver
|
||||||
|
homeserverURL := config.HomeserverURL
|
||||||
|
if homeserverURL == "" {
|
||||||
|
homeserverURL = os.Getenv("MATRIX_HOMESERVER_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the user id
|
||||||
|
userID := config.UserID
|
||||||
|
if userID == "" {
|
||||||
|
userID = os.Getenv("MATRIX_USER_ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the access token
|
||||||
|
accessToken := config.AccessToken
|
||||||
|
if accessToken == "" {
|
||||||
|
accessToken = os.Getenv("MATRIX_ACCESS_TOKEN")
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the room id
|
||||||
|
roomID := config.RoomID
|
||||||
|
if roomID == "" {
|
||||||
|
roomID = os.Getenv("MATRIX_ROOM_ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a new client for matrix
|
||||||
|
client, err := gomatrix.NewClient(homeserverURL, userID, accessToken)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, colors.BrightRed+"error creating Matrix client:"+colors.Nc, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a buffer for msg chunking
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
buffer := ""
|
||||||
|
for scanner.Scan() {
|
||||||
|
text := strings.TrimSpace(scanner.Text())
|
||||||
|
if text == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newBuffer := buffer + "\n" + text
|
||||||
|
|
||||||
|
// if what we're getting is bigger
|
||||||
|
// than max msg size, send what we have
|
||||||
|
if len(newBuffer) > maxMessageSize {
|
||||||
|
|
||||||
|
// send it
|
||||||
|
sendMessage(client, roomID, buffer)
|
||||||
|
buffer = text
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// and if it isn't, add it
|
||||||
|
buffer = newBuffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep talking till the buffer's empty
|
||||||
|
if len(buffer) > 0 {
|
||||||
|
sendMessage(client, roomID, buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, colors.BrightRed+"error reading standard input:"+colors.Nc, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendMessage(client *gomatrix.Client, roomID, message string) {
|
||||||
|
|
||||||
|
// if we use -c or --code, make it a ```this thing```
|
||||||
|
if codeFlag {
|
||||||
|
message = "<pre><code>" + message + "</code></pre>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the message to the room in tne cofing
|
||||||
|
_, err := client.SendText(roomID, message)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, colors.BrightRed+"error sending message to Matrix:"+colors.Nc, err)
|
||||||
|
os.Exit(1)
|
||||||
|
} else {
|
||||||
|
fmt.Println(colors.BrightGreen + "Sent!" + colors.Nc)
|
||||||
|
}
|
||||||
|
time.Sleep(messageDelay)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue