2020-12-11 17:20:44 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-12-17 04:23:25 +00:00
|
|
|
"encoding/json"
|
2020-12-11 17:20:44 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2020-12-17 01:15:17 +00:00
|
|
|
type ImageData struct {
|
2020-12-17 04:23:25 +00:00
|
|
|
Type string `"json:type"`
|
|
|
|
Url string `"json:url"`
|
2020-12-17 01:15:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type PublicKeyData struct {
|
2020-12-17 04:23:25 +00:00
|
|
|
Id string `"json:id"`
|
|
|
|
Owner string `"json:owner"`
|
|
|
|
PublicKeyPem string `"json:publicKeyPem"`
|
2020-12-17 01:15:17 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 06:21:18 +00:00
|
|
|
type UserInfo struct {
|
2020-12-17 04:23:25 +00:00
|
|
|
Id string `"json:id"`
|
|
|
|
Type string `"json:type"`
|
|
|
|
Following string `"json:following"`
|
|
|
|
Followers string `"json:followers"`
|
|
|
|
Inbox string `"json:inbox"`
|
|
|
|
Outbox string `"json:outbox"`
|
|
|
|
Featured string `"json:featured"`
|
|
|
|
PreferredUsername string `"json:preferredUsername"`
|
|
|
|
PublicKey PublicKeyData `"json:publicKeyPem"`
|
|
|
|
Name string `"json:name"`
|
|
|
|
Summary string `"json:summary"`
|
|
|
|
Url string `"json:Url"`
|
2020-12-17 18:26:55 +00:00
|
|
|
Icon ImageData `"json:icon"`
|
|
|
|
Image ImageData `"json:image"`
|
2020-12-17 04:23:25 +00:00
|
|
|
|
|
|
|
// ManuallyApprovesFollowers string `"json:manuallyApprovesFollowers"`
|
|
|
|
// Discoverable bool `"json:discoverable"`
|
2020-12-16 06:21:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type PostInfo struct {
|
2020-12-17 04:23:25 +00:00
|
|
|
Id string `"json:id"`
|
|
|
|
Type string `"json:type"`
|
|
|
|
Published string `"json:published"`
|
|
|
|
Url string `"json:Url"`
|
|
|
|
Content string `"json:content"`
|
2020-12-16 06:21:18 +00:00
|
|
|
}
|
|
|
|
|
2020-12-25 05:18:42 +00:00
|
|
|
func PollMastodonPleroma(endpoint string, o *RunningInstance) {
|
2021-02-01 12:52:42 +00:00
|
|
|
newactivities := make([]ReportActivity, 0)
|
2020-12-11 17:20:44 +00:00
|
|
|
|
|
|
|
min_id := ""
|
|
|
|
|
|
|
|
parsing_error := 0
|
|
|
|
use_auth := false
|
|
|
|
|
|
|
|
var last_refresh int64
|
|
|
|
var client_id string
|
|
|
|
var client_secret string
|
|
|
|
var oauthData OAuth
|
|
|
|
var err error
|
|
|
|
|
|
|
|
for _, extaccount := range settings.Externalaccounts {
|
|
|
|
if extaccount.Endpoint == endpoint {
|
|
|
|
use_auth = true
|
2021-01-29 17:44:16 -05:00
|
|
|
o, _ := GetRunner(endpoint)
|
2020-12-25 05:18:42 +00:00
|
|
|
err = get_client(endpoint, &o)
|
2020-12-11 17:20:44 +00:00
|
|
|
if err != nil {
|
2021-01-14 19:51:42 +00:00
|
|
|
logErr.Print("Unable to register client for " + endpoint + ": ", err)
|
2020-12-23 08:20:03 +00:00
|
|
|
return
|
2020-12-11 17:20:44 +00:00
|
|
|
}
|
|
|
|
|
2020-12-25 05:18:42 +00:00
|
|
|
oauthData, err = oauth_login(endpoint, &o, extaccount.Username, extaccount.Password)
|
2020-12-11 17:20:44 +00:00
|
|
|
if err != nil {
|
2021-01-14 19:51:42 +00:00
|
|
|
logErr.Print("Unable to login to " + endpoint + ": ", err)
|
2020-12-11 17:20:44 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
last_refresh = time.Now().Unix()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for {
|
|
|
|
ri_mutex.Lock()
|
|
|
|
m := runninginstances[endpoint]
|
|
|
|
ri_mutex.Unlock()
|
|
|
|
|
|
|
|
api_timeline := "https://" + endpoint + "/api/v1/timelines/public?limit=40&since_id=" + min_id
|
|
|
|
req, err := http.NewRequest("GET", api_timeline, nil)
|
2021-01-25 21:06:47 -05:00
|
|
|
req.Header.Set("User-Agent", "Tusky")
|
2020-12-11 17:20:44 +00:00
|
|
|
if err != nil {
|
2021-01-14 19:51:42 +00:00
|
|
|
logFatal.Fatal("Unable to create new request for " + endpoint + ": ", err)
|
2020-12-11 17:20:44 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if use_auth == true {
|
2020-12-17 04:23:25 +00:00
|
|
|
if time.Now().Unix() > last_refresh+oauthData.Expires_in {
|
2020-12-11 17:20:44 +00:00
|
|
|
oauthData, err = oauth_refresh(endpoint, client_id, client_secret, oauthData.Refresh_token)
|
|
|
|
if err != nil {
|
2021-01-14 19:51:42 +00:00
|
|
|
logWarn.Fatal("Unable to refresh oauth token for " + endpoint + ": ", err)
|
2020-12-11 17:20:44 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
last_refresh = time.Now().Unix()
|
|
|
|
}
|
|
|
|
req.Header.Add("Authorization", oauthData.Access_token)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.LastRun = time.Now().Format(time.RFC3339)
|
2021-01-14 19:51:42 +00:00
|
|
|
resp, err := DoTries(o, req)
|
2020-12-11 17:20:44 +00:00
|
|
|
if err != nil {
|
|
|
|
m.Status = CLIENT_ISSUE
|
2020-12-17 01:15:17 +00:00
|
|
|
ri_mutex.Lock()
|
2020-12-11 17:20:44 +00:00
|
|
|
runninginstances[endpoint] = m
|
|
|
|
ri_mutex.Unlock()
|
2021-01-14 19:51:42 +00:00
|
|
|
logWarn.Print("Giving up on " + endpoint + ": ", err.Error())
|
2020-12-11 17:20:44 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if resp.StatusCode == TOOMANYREQUESTS { // Short Delay, 30 seconds
|
2021-01-14 19:51:42 +00:00
|
|
|
logWarn.Print("Delaying "+endpoint+", gave status ", resp.StatusCode, ", 1 hour delay")
|
2020-12-11 17:20:44 +00:00
|
|
|
_, _ = ioutil.ReadAll(resp.Body)
|
|
|
|
resp.Body.Close() // Release as soon as done
|
|
|
|
m.Status = resp.StatusCode
|
2020-12-17 01:15:17 +00:00
|
|
|
ri_mutex.Lock()
|
2020-12-11 17:20:44 +00:00
|
|
|
runninginstances[endpoint] = m
|
|
|
|
ri_mutex.Unlock()
|
|
|
|
time.Sleep(time.Second * 30)
|
|
|
|
continue
|
|
|
|
} else if resp.StatusCode == INTERNAL_ERROR { // Longer delay, 1 hour
|
2021-01-14 19:51:42 +00:00
|
|
|
logWarn.Print("Suspending " + endpoint + ", gave status ", resp.StatusCode, ", 1 hour delay")
|
2020-12-11 17:20:44 +00:00
|
|
|
_, _ = ioutil.ReadAll(resp.Body)
|
|
|
|
resp.Body.Close() // Release as soon as done
|
|
|
|
m.Status = 765
|
2020-12-17 01:15:17 +00:00
|
|
|
ri_mutex.Lock()
|
2020-12-11 17:20:44 +00:00
|
|
|
runninginstances[endpoint] = m
|
|
|
|
ri_mutex.Unlock()
|
|
|
|
time.Sleep(time.Second * 3600)
|
|
|
|
continue
|
|
|
|
} else if resp.StatusCode != 200 { // Crash
|
2021-01-14 19:51:42 +00:00
|
|
|
logErr.Print("Terminating " + endpoint + ", gave status ", resp.StatusCode)
|
2020-12-11 17:20:44 +00:00
|
|
|
_, _ = ioutil.ReadAll(resp.Body)
|
|
|
|
resp.Body.Close() // Release as soon as done
|
|
|
|
m.Status = resp.StatusCode
|
2020-12-17 01:15:17 +00:00
|
|
|
ri_mutex.Lock()
|
2020-12-11 17:20:44 +00:00
|
|
|
runninginstances[endpoint] = m
|
|
|
|
ri_mutex.Unlock()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-02-01 12:52:42 +00:00
|
|
|
err = json.NewDecoder(resp.Body).Decode(&newactivities)
|
2021-01-30 14:30:49 +00:00
|
|
|
resp.Body.Close() // Release as soon as done
|
2020-12-11 17:20:44 +00:00
|
|
|
if err != nil {
|
|
|
|
if parsing_error > 5 {
|
|
|
|
m.Status = BAD_RESPONSE
|
2020-12-17 01:15:17 +00:00
|
|
|
ri_mutex.Lock()
|
2020-12-11 17:20:44 +00:00
|
|
|
runninginstances[endpoint] = m
|
|
|
|
ri_mutex.Unlock()
|
2021-01-14 19:51:42 +00:00
|
|
|
logErr.Print("Giving up on " + endpoint + " after 5 unmarshal errors.")
|
2020-12-11 17:20:44 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
parsing_error = parsing_error + 1
|
|
|
|
time.Sleep(time.Second * 30)
|
|
|
|
}
|
2021-01-30 14:30:49 +00:00
|
|
|
// resp.Body.Close() // Release as soon as done
|
2020-12-11 17:20:44 +00:00
|
|
|
|
|
|
|
m.Status = RUNNING
|
2020-12-17 01:15:17 +00:00
|
|
|
ri_mutex.Lock()
|
2020-12-11 17:20:44 +00:00
|
|
|
runninginstances[endpoint] = m
|
|
|
|
ri_mutex.Unlock()
|
|
|
|
|
2021-02-01 12:52:42 +00:00
|
|
|
for _, newactivity := range newactivities {
|
|
|
|
go check_activity(newactivity.Uri)
|
|
|
|
matchset := re.FindStringSubmatch(newactivity.Uri)
|
2021-01-10 21:47:08 +00:00
|
|
|
if matchset != nil {
|
|
|
|
newinstance := matchset[1]
|
2021-01-10 05:31:51 +00:00
|
|
|
|
2021-01-10 21:47:08 +00:00
|
|
|
// Check min_id
|
2021-02-01 12:52:42 +00:00
|
|
|
if newactivity.Id > min_id {
|
|
|
|
min_id = newactivity.Id
|
2021-01-10 21:47:08 +00:00
|
|
|
}
|
2020-12-17 01:15:17 +00:00
|
|
|
|
2021-01-10 21:47:08 +00:00
|
|
|
go CheckInstance(newinstance, endpoint)
|
2020-12-11 17:20:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
time.Sleep(time.Second * 10)
|
|
|
|
}
|
|
|
|
}
|