@ -0,0 +1,29 @@ |
|||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects) |
||||
|
*.o |
||||
|
*.a |
||||
|
*.so |
||||
|
|
||||
|
# Folders |
||||
|
_obj |
||||
|
_test |
||||
|
|
||||
|
# Architecture specific extensions/prefixes |
||||
|
*.[568vq] |
||||
|
[568vq].out |
||||
|
|
||||
|
*.cgo1.go |
||||
|
*.cgo2.c |
||||
|
_cgo_defun.c |
||||
|
_cgo_gotypes.go |
||||
|
_cgo_export.* |
||||
|
|
||||
|
_testmain.go |
||||
|
|
||||
|
*.exe |
||||
|
*.test |
||||
|
*.prof |
||||
|
|
||||
|
|
||||
|
twitterConfig.json |
||||
|
matrixConfig.json |
||||
|
temp |
@ -0,0 +1,33 @@ |
|||||
|
# twitterDM-to-matrix [![Go Report Card](https://goreportcard.com/badge/github.com/arnaucode/twitterDM-to-matrix)](https://goreportcard.com/report/github.com/arnaucode/twitterDM-to-matrix) |
||||
|
|
||||
|
bridge to send the received twitter Direct Messages (https://twitter.com) to a Matrix room (https://matrix.org), written in Go |
||||
|
|
||||
|
|
||||
|
needs a twitterConfig.json file on the /build folder with the content: |
||||
|
``` |
||||
|
{ |
||||
|
"consumer_key": "xxxxxxxxxxxxxxxx", |
||||
|
"consumer_secret": "xxxxxxxxxxxxxxxx", |
||||
|
"access_token_key": "xxxxxxxxxxxxxxxx", |
||||
|
"access_token_secret": "xxxxxxxxxxxxxxxx" |
||||
|
} |
||||
|
|
||||
|
``` |
||||
|
and a matrixConfig.json file on the /build folder with the content: |
||||
|
``` |
||||
|
{ |
||||
|
"room_id": "xxxxx", |
||||
|
"user": "xxxxx", |
||||
|
"password": "xxxxx", |
||||
|
"server": "https://xxxxx.xxxxx" |
||||
|
} |
||||
|
|
||||
|
``` |
||||
|
|
||||
|
to run it: |
||||
|
- go to the /build folder |
||||
|
- open terminal |
||||
|
- execute the script with: |
||||
|
``` |
||||
|
./twitterDM-to-matrix |
||||
|
``` |
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"room_id": "xxxxx", |
||||
|
"user": "xxxxx", |
||||
|
"password": "xxxxx", |
||||
|
"server": "https://xxxxx.xxxxx" |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"screenName": "xxxxx", |
||||
|
"consumer_key": "xxxxx", |
||||
|
"consumer_secret": "xxxxx", |
||||
|
"access_token": "xxxxx", |
||||
|
"access_token_secret": "xxxxx" |
||||
|
} |
@ -0,0 +1,57 @@ |
|||||
|
package main |
||||
|
|
||||
|
import "fmt" |
||||
|
|
||||
|
//Color struct, defines the color
|
||||
|
type Color struct{} |
||||
|
|
||||
|
var c Color |
||||
|
|
||||
|
//DarkGray color
|
||||
|
func (c Color) DarkGray(t string) { |
||||
|
fmt.Print("\x1b[30;1m") //dark gray
|
||||
|
fmt.Println(t) |
||||
|
fmt.Print("\x1b[0m") //defaultColor
|
||||
|
} |
||||
|
|
||||
|
//Red color
|
||||
|
func (c Color) Red(t string) { |
||||
|
fmt.Print("\x1b[31;1m") //red
|
||||
|
fmt.Println(t) |
||||
|
fmt.Print("\x1b[0m") //defaultColor
|
||||
|
} |
||||
|
|
||||
|
//Green color
|
||||
|
func (c Color) Green(t string) { |
||||
|
fmt.Print("\x1b[32;1m") //green
|
||||
|
fmt.Println(t) |
||||
|
fmt.Print("\x1b[0m") //defaultColor
|
||||
|
} |
||||
|
|
||||
|
//Yellow color
|
||||
|
func (c Color) Yellow(t string) { |
||||
|
fmt.Print("\x1b[33;1m") //yellow
|
||||
|
fmt.Println(t) |
||||
|
fmt.Print("\x1b[0m") //defaultColor
|
||||
|
} |
||||
|
|
||||
|
//Blue color
|
||||
|
func (c Color) Blue(t string) { |
||||
|
fmt.Print("\x1b[34;1m") //blue
|
||||
|
fmt.Println(t) |
||||
|
fmt.Print("\x1b[0m") //defaultColor
|
||||
|
} |
||||
|
|
||||
|
//Purple color
|
||||
|
func (c Color) Purple(t string) { |
||||
|
fmt.Print("\x1b[35;1m") //purple
|
||||
|
fmt.Println(t) |
||||
|
fmt.Print("\x1b[0m") //defaultColor
|
||||
|
} |
||||
|
|
||||
|
//Cyan color
|
||||
|
func (c Color) Cyan(t string) { |
||||
|
fmt.Print("\x1b[36;1m") //cyan
|
||||
|
fmt.Println(t) |
||||
|
fmt.Print("\x1b[0m") //defaultColor
|
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
) |
||||
|
|
||||
|
const version = "0.1-dev" |
||||
|
|
||||
|
func main() { |
||||
|
c.Green("twitterDM-to-matrix") |
||||
|
c.Yellow("version: " + version) |
||||
|
c.Green("bridge twitter DM to Matrix") |
||||
|
fmt.Println("configuring") |
||||
|
|
||||
|
c.Purple("------matrix------") |
||||
|
readMatrixConfig() |
||||
|
loginMatrix() |
||||
|
fmt.Print("matrix token: ") |
||||
|
c.Cyan(matrixToken.AccessToken) |
||||
|
fmt.Println("") |
||||
|
|
||||
|
c.Purple("------twitter------") |
||||
|
client := readTwitterConfigTokensAndConnect() |
||||
|
user := getUserData(client) |
||||
|
printTwitterUserData(user) |
||||
|
fmt.Println("") |
||||
|
|
||||
|
c.Purple("------starting to listen------") |
||||
|
|
||||
|
stream(client) |
||||
|
} |
@ -0,0 +1,86 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
"io/ioutil" |
||||
|
"log" |
||||
|
"math/rand" |
||||
|
"net/http" |
||||
|
"strconv" |
||||
|
"strings" |
||||
|
) |
||||
|
|
||||
|
//MatrixConfig stores the data from json matrixConfig.json file
|
||||
|
type MatrixConfig struct { |
||||
|
RoomId string `json:"room_id"` |
||||
|
User string `json:"user"` |
||||
|
Password string `json:"password"` |
||||
|
Server string `json:"server"` |
||||
|
} |
||||
|
|
||||
|
//MatrixToken stores the token data from matrix
|
||||
|
type MatrixToken struct { |
||||
|
AccessToken string `json:"access_token"` |
||||
|
Server string `json:"server"` |
||||
|
UserId string `json:"user_id"` |
||||
|
DeviceId string `json:"device_id"` |
||||
|
} |
||||
|
|
||||
|
var matrixConfig MatrixConfig |
||||
|
var matrixToken MatrixToken |
||||
|
|
||||
|
func readMatrixConfig() { |
||||
|
file, e := ioutil.ReadFile("matrixConfig.json") |
||||
|
if e != nil { |
||||
|
fmt.Println("error:", e) |
||||
|
} |
||||
|
content := string(file) |
||||
|
json.Unmarshal([]byte(content), &matrixConfig) |
||||
|
} |
||||
|
|
||||
|
func loginMatrix() { |
||||
|
url := matrixConfig.Server + "/_matrix/client/r0/login" |
||||
|
jsonStr := `{ |
||||
|
"type":"m.login.password", |
||||
|
"user":"` + matrixConfig.User + `", |
||||
|
"password":"` + matrixConfig.Password + `" |
||||
|
}` |
||||
|
b := strings.NewReader(jsonStr) |
||||
|
req, _ := http.NewRequest("POST", url, b) |
||||
|
req.Header.Set("Content-Type", "application/json") |
||||
|
res, err := http.DefaultClient.Do(req) |
||||
|
if err != nil { |
||||
|
log.Println(err) |
||||
|
} |
||||
|
defer res.Body.Close() |
||||
|
body, _ := ioutil.ReadAll(res.Body) |
||||
|
|
||||
|
json.Unmarshal([]byte(body), &matrixToken) |
||||
|
|
||||
|
} |
||||
|
func matrixSendMsg(senderScreenName string, message string, createdAt string) { |
||||
|
txnId := strconv.Itoa(rand.Int()) |
||||
|
c.Green(txnId) |
||||
|
url := matrixConfig.Server + "/_matrix/client/r0/rooms/" + matrixConfig.RoomId + "/send/m.room.message/" + txnId + "?access_token=" + matrixToken.AccessToken |
||||
|
jsonStr := `{ |
||||
|
"body":"[NEW DM] - at ` + createdAt + `\n@` + senderScreenName + `: ` + message + `", |
||||
|
"msgtype":"m.text" |
||||
|
}` |
||||
|
b := strings.NewReader(jsonStr) |
||||
|
req, _ := http.NewRequest("PUT", url, b) |
||||
|
req.Header.Set("Content-Type", "application/json") |
||||
|
res, err := http.DefaultClient.Do(req) |
||||
|
if err != nil { |
||||
|
log.Println(err) |
||||
|
} |
||||
|
defer res.Body.Close() |
||||
|
body, _ := ioutil.ReadAll(res.Body) |
||||
|
|
||||
|
fmt.Println(string(body)) |
||||
|
|
||||
|
fmt.Println(createdAt) |
||||
|
fmt.Print("received DM sent to Matrix: ") |
||||
|
c.Green(message) |
||||
|
|
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
"io/ioutil" |
||||
|
|
||||
|
"github.com/dghubble/go-twitter/twitter" |
||||
|
"github.com/dghubble/oauth1" |
||||
|
) |
||||
|
|
||||
|
//TwitterConfig stores the data from json twitterConfig.json file
|
||||
|
type TwitterConfig struct { |
||||
|
ScreenName string `json:"screenName"` |
||||
|
ConsumerKey string `json:"consumer_key"` |
||||
|
ConsumerSecret string `json:"consumer_secret"` |
||||
|
AccessToken string `json:"access_token"` |
||||
|
AccessTokenSecret string `json:"access_token_secret"` |
||||
|
} |
||||
|
|
||||
|
var twitterConfig TwitterConfig |
||||
|
|
||||
|
func readTwitterConfigTokensAndConnect() (client *twitter.Client) { |
||||
|
|
||||
|
file, e := ioutil.ReadFile("twitterConfig.json") |
||||
|
if e != nil { |
||||
|
fmt.Println("error:", e) |
||||
|
} |
||||
|
content := string(file) |
||||
|
json.Unmarshal([]byte(content), &twitterConfig) |
||||
|
fmt.Println("twitterConfig.json read comlete") |
||||
|
|
||||
|
fmt.Print("connecting to twitter api --> ") |
||||
|
configu := oauth1.NewConfig(twitterConfig.ConsumerKey, twitterConfig.ConsumerSecret) |
||||
|
token := oauth1.NewToken(twitterConfig.AccessToken, twitterConfig.AccessTokenSecret) |
||||
|
httpClient := configu.Client(oauth1.NoContext, token) |
||||
|
// twitter client
|
||||
|
client = twitter.NewClient(httpClient) |
||||
|
|
||||
|
fmt.Println("connection successful") |
||||
|
|
||||
|
return client |
||||
|
} |
@ -0,0 +1,46 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"log" |
||||
|
"os" |
||||
|
"os/signal" |
||||
|
"syscall" |
||||
|
|
||||
|
"github.com/dghubble/go-twitter/twitter" |
||||
|
) |
||||
|
|
||||
|
func stream(client *twitter.Client) { |
||||
|
// Convenience Demux demultiplexed stream messages
|
||||
|
demux := twitter.NewSwitchDemux() |
||||
|
|
||||
|
demux.All = func(message interface{}) { |
||||
|
//fmt.Println(message)
|
||||
|
} |
||||
|
demux.DM = func(dm *twitter.DirectMessage) { |
||||
|
if dm.SenderScreenName != twitterConfig.ScreenName { |
||||
|
matrixSendMsg(dm.SenderScreenName, dm.Text, dm.CreatedAt) |
||||
|
} |
||||
|
} |
||||
|
demux.Event = func(event *twitter.Event) { |
||||
|
//fmt.Printf("%#v\n", event)
|
||||
|
} |
||||
|
|
||||
|
fmt.Println("Starting Stream...") |
||||
|
|
||||
|
streamUserParams := &twitter.StreamUserParams{} |
||||
|
stream, err := client.Streams.User(streamUserParams) |
||||
|
if err != nil { |
||||
|
log.Fatal(err) |
||||
|
} |
||||
|
|
||||
|
// Receive messages until stopped or stream quits
|
||||
|
demux.HandleChan(stream.Messages) |
||||
|
|
||||
|
ch := make(chan os.Signal) |
||||
|
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) |
||||
|
log.Println(<-ch) |
||||
|
|
||||
|
fmt.Println("Stopping Stream...") |
||||
|
stream.Stop() |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
|
||||
|
"github.com/dghubble/go-twitter/twitter" |
||||
|
) |
||||
|
|
||||
|
func getUserData(client *twitter.Client) *twitter.User { |
||||
|
// Verify Credentials
|
||||
|
verifyParams := &twitter.AccountVerifyParams{ |
||||
|
SkipStatus: twitter.Bool(true), |
||||
|
IncludeEmail: twitter.Bool(true), |
||||
|
} |
||||
|
user, _, _ := client.Accounts.VerifyCredentials(verifyParams) |
||||
|
return user |
||||
|
} |
||||
|
func printTwitterUserData(user *twitter.User) { |
||||
|
fmt.Print("username: ") |
||||
|
c.Cyan(user.Name + " @" + user.ScreenName) |
||||
|
if user.Email != "" { |
||||
|
fmt.Print("Email ") |
||||
|
c.Red(user.Email) |
||||
|
} |
||||
|
if user.Location != "" { |
||||
|
fmt.Print("Location: ") |
||||
|
c.Red(user.Location) |
||||
|
} |
||||
|
fmt.Print("user created on: ") |
||||
|
c.Cyan(user.CreatedAt) |
||||
|
} |