175 lines
3.5 KiB
Go
175 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"flag"
|
|
|
|
"github.com/McKael/madon/v2"
|
|
"github.com/jaytaylor/html2text"
|
|
r "gopkg.in/rethinkdb/rethinkdb-go.v6"
|
|
"within.website/ln"
|
|
"within.website/ln/opname"
|
|
)
|
|
|
|
var (
|
|
// Mastodon
|
|
mastodonInstance = flag.String("mastodon-instance", "", "Mastodon instance to connect to")
|
|
mastodonAppID = flag.String("mastodon-app-id", "", "Mastodon app ID")
|
|
mastodonAppSecret = flag.String("mastodon-app-secret", "", "Mastodon app secret")
|
|
mastodonToken = flag.String("mastodon-token", "", "Mastodon API token")
|
|
mastodonAccount = flag.String("mastodon-account", "", "Mastodon account")
|
|
)
|
|
|
|
func makeMastodon() (*madon.Client, error) {
|
|
c, err := madon.RestoreApp("mi", *mastodonInstance, *mastodonAppID, *mastodonAppSecret, &madon.UserToken{AccessToken: *mastodonToken})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return c, nil
|
|
}
|
|
|
|
func (mi *Mi) StreamMastodon(ctx context.Context) error {
|
|
evChan := make(chan madon.StreamEvent, 10)
|
|
stop := make(chan bool)
|
|
done := make(chan bool)
|
|
ctx = opname.With(context.Background(), "user-stream")
|
|
|
|
err := mi.mastodonClient.StreamListener("user", "", evChan, stop, done)
|
|
if err != nil {
|
|
ln.FatalErr(ctx, err)
|
|
}
|
|
|
|
ln.Log(ctx, ln.Info("streaming user toots to rethinkdb"))
|
|
|
|
for {
|
|
select {
|
|
case <-done:
|
|
ln.Fatal(ctx, ln.Action("got done?"))
|
|
case <-ctx.Done():
|
|
stop <- true
|
|
case ev := <-evChan:
|
|
s, ok := ev.Data.(madon.Status)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if s.Account.Acct != *mastodonAccount {
|
|
continue
|
|
}
|
|
|
|
if s.Reblog != nil {
|
|
continue
|
|
}
|
|
|
|
err := r.Table("mastodon").Insert(s).Exec(mi.session)
|
|
if err != nil {
|
|
ln.Error(ctx, err)
|
|
stop <- true
|
|
}
|
|
|
|
ln.Log(ctx, ln.Info("got toot"), ln.F{
|
|
"toot_url": s.URL,
|
|
"toot_creator": s.Account.Username,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
type NewStatus struct {
|
|
NewVal *madon.Status `json:"new_val"`
|
|
OldVal *madon.Status `json:"old_val"`
|
|
}
|
|
|
|
func (mi *Mi) PushMastodon(ctx context.Context, p Post) error {
|
|
_, err := mi.mastodonClient.PostStatus(madon.PostStatusParams{
|
|
Text: p.Format(),
|
|
Visibility: "public",
|
|
})
|
|
return err
|
|
}
|
|
|
|
func (mi *Mi) StreamMastodonToTwitter(ctx context.Context) {
|
|
res, err := r.Table("mastodon").Changes().Run(mi.session)
|
|
if err != nil {
|
|
ln.FatalErr(ctx, err)
|
|
}
|
|
defer res.Close()
|
|
|
|
ln.Log(ctx, ln.Info("streaming mastodon to twitter"))
|
|
|
|
for {
|
|
data, ok := res.NextResponse()
|
|
if !ok {
|
|
ln.FatalErr(ctx, res.Err())
|
|
}
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
break
|
|
default:
|
|
}
|
|
|
|
var ns NewStatus
|
|
err := json.Unmarshal(data, &ns)
|
|
if err != nil {
|
|
ln.FatalErr(ctx, err)
|
|
}
|
|
|
|
if ns.NewVal == nil {
|
|
continue
|
|
}
|
|
|
|
st := ns.NewVal
|
|
|
|
if st.Visibility != "public" {
|
|
continue
|
|
}
|
|
|
|
if st.Application.Name == "mi_irl" {
|
|
continue
|
|
}
|
|
|
|
if st.Sensitive {
|
|
continue
|
|
}
|
|
|
|
if st.Account.Acct != *mastodonAccount {
|
|
continue
|
|
}
|
|
|
|
if st.InReplyToID != nil {
|
|
continue
|
|
}
|
|
|
|
text, err := html2text.FromString(st.Content, html2text.Options{OmitLinks: true})
|
|
if len(text) > 200 {
|
|
text = text[:200] + "... read more here: " + st.URL
|
|
}
|
|
if err != nil {
|
|
ln.Error(ctx, err, ln.F{"url": st.URL})
|
|
continue
|
|
}
|
|
|
|
tweet, _, err := mi.twitterClient.Statuses.Update(text, nil)
|
|
if err != nil {
|
|
ln.Error(ctx, err, ln.F{
|
|
"text": text,
|
|
"url": st.URL,
|
|
})
|
|
continue
|
|
}
|
|
|
|
ln.Log(ctx, ln.Info("sent tweet from mastodon"), ln.F{
|
|
"tweet_id": tweet.ID,
|
|
})
|
|
|
|
err = r.Table("tweets").Insert(tweet).Exec(mi.session)
|
|
if err != nil {
|
|
ln.Error(ctx, err)
|
|
continue
|
|
}
|
|
}
|
|
}
|