aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorFChannel <>2021-07-28 15:31:37 -0700
committerFChannel <>2021-07-28 15:31:37 -0700
commit98d72c9b94b5dda9a987dfe41552f00512d43574 (patch)
treeef75468766c6c5e2d4392cfc567eb29cb90d0c9d /main.go
parentea12d0f741455c542accf24a003a62ab85bfbfa3 (diff)
parent87fc54c9d41bdbe7eaa8769386776a3723580b34 (diff)
v0.0.13-release
Diffstat (limited to 'main.go')
-rw-r--r--main.go261
1 files changed, 221 insertions, 40 deletions
diff --git a/main.go b/main.go
index 4327e44..17ed9d1 100644
--- a/main.go
+++ b/main.go
@@ -49,6 +49,8 @@ var activitystreams = "application/ld+json; profile=\"https://www.w3.org/ns/acti
var MediaHashs = make(map[string]string)
+var ActorCache = make(map[string]Actor)
+
func main() {
CreatedNeededDirectories()
@@ -270,7 +272,7 @@ func main() {
auth := CreateTripCode(verify.Code)
auth = CreateTripCode(auth)
-
+
if CreateTripCode(auth) == code {
w.WriteHeader(http.StatusOK)
} else {
@@ -334,8 +336,8 @@ func main() {
}
if(r.FormValue("inReplyTo") == "" && file == nil) {
- w.Write([]byte("Media is required for new posts"))
- return
+ w.Write([]byte("Media is required for new posts"))
+ return
}
@@ -500,7 +502,7 @@ func main() {
}
}
- //follow all of boards followers
+ //follow all of boards followers
} else if followers.MatchString(follow){
followersActor := FingerActor(follow)
col := GetActorCollection(followersActor.Followers)
@@ -519,7 +521,7 @@ func main() {
}
}
- //do a normal follow to a single board
+ //do a normal follow to a single board
} else {
followActivity := MakeFollowActivity(db, actorId, follow)
@@ -601,7 +603,7 @@ func main() {
} else if admin || actor.Id == Domain {
t := template.Must(template.New("").Funcs(template.FuncMap{
"sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/nadmin.html"))
-
+
actor := GetActor(Domain)
follow := GetActorCollection(actor.Following).Items
follower := GetActorCollection(actor.Followers).Items
@@ -769,7 +771,96 @@ func main() {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("404 no path"))
}
- })
+ })
+
+ http.HandleFunc("/banmedia", func(w http.ResponseWriter, r *http.Request) {
+ id := r.URL.Query().Get("id")
+ board := r.URL.Query().Get("board")
+
+ _, auth := GetPasswordFromSession(r)
+
+ if id == "" || auth == "" {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ return
+ }
+
+ col := GetCollectionFromID(id)
+
+ if len(col.OrderedItems) > 0 {
+
+ actor := col.OrderedItems[0].Actor
+
+ if !HasAuth(db, auth, actor) {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ return
+ }
+
+ if len(col.OrderedItems[0].Attachment) > 0 {
+ re := regexp.MustCompile(Domain)
+ file := re.ReplaceAllString(col.OrderedItems[0].Attachment[0].Href, "")
+
+ f, err := os.Open("." + file)
+ CheckError(err, "could not open attachment for ban media")
+
+ defer f.Close()
+
+ bytes := make([]byte, 2048)
+
+ _, err = f.Read(bytes)
+ if err != nil {
+ fmt.Println("error readin bytes for setting media ban")
+ }
+
+ if !IsMediaBanned(db, f) {
+ query := `insert into bannedmedia (hash) values ($1)`
+
+ _, err := db.Exec(query, HashBytes(bytes))
+
+ CheckError(err, "error inserting banend media into db")
+
+ }
+
+ var obj ObjectBase
+ obj.Id = id
+ obj.Actor = actor
+
+ isOP := CheckIfObjectOP(db, obj.Id)
+
+ var OP string
+ if len(col.OrderedItems[0].InReplyTo) > 0 {
+ OP = col.OrderedItems[0].InReplyTo[0].Id
+ }
+
+ if !isOP {
+ TombstoneObject(db, id)
+ } else {
+ TombstoneObjectAndReplies(db, id)
+ }
+
+ if IsIDLocal(db, id){
+ go DeleteObjectRequest(db, id)
+ }
+
+
+ if !isOP {
+ if (!IsIDLocal(db, id)){
+ http.Redirect(w, r, "/" + board + "/" + remoteShort(OP), http.StatusSeeOther)
+ return
+ } else {
+ http.Redirect(w, r, OP, http.StatusSeeOther)
+ return
+ }
+ } else {
+ http.Redirect(w, r, "/" + board, http.StatusSeeOther)
+ return
+ }
+ }
+ }
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ })
http.HandleFunc("/delete", func(w http.ResponseWriter, r *http.Request){
id := r.URL.Query().Get("id")
@@ -1197,7 +1288,13 @@ func main() {
return
}
- if !IsActorLocal(db, TP + "" + actorDomain[1] + "/" + actorDomain[0]) {
+ if actorDomain[0] == "main" {
+ actorDomain[0] = ""
+ } else {
+ actorDomain[0] = "/" + actorDomain[0]
+ }
+
+ if !IsActorLocal(db, TP + "" + actorDomain[1] + "" + actorDomain[0]) {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("actor not local"))
return
@@ -1209,7 +1306,7 @@ func main() {
finger.Subject = "acct:" + actorDomain[0] + "@" + actorDomain[1]
link.Rel = "self"
link.Type = "application/activity+json"
- link.Href = TP + "" + actorDomain[1] + "/" + actorDomain[0]
+ link.Href = TP + "" + actorDomain[1] + "" + actorDomain[0]
finger.Links = append(finger.Links, link)
@@ -1369,7 +1466,6 @@ func CreateTripCode(input string) string {
return code[0]
}
-
func GetActorFromPath(db *sql.DB, location string, prefix string) Actor {
pattern := fmt.Sprintf("%s([^/\n]+)(/.+)?", prefix)
re := regexp.MustCompile(pattern)
@@ -1639,9 +1735,9 @@ func CreateAttachmentObject(file multipart.File, header *multipart.FileHeader) (
return nAttachment, tempFile
}
-func ParseCommentForReplies(comment string) []ObjectBase {
-
- re := regexp.MustCompile("(>>)(https://|http://)?(www\\.)?.+\\/\\w+")
+func ParseCommentForReplies(db *sql.DB, comment string, op string) []ObjectBase {
+
+ re := regexp.MustCompile(`(>>(https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/)(f[A-Za-z0-9_.\-~]+-)?([A-Za-z0-9_.\-~]+)?#?([A-Za-z0-9_.\-~]+)?)`)
match := re.FindAllStringSubmatch(comment, -1)
var links []string
@@ -1652,7 +1748,8 @@ func ParseCommentForReplies(comment string) []ObjectBase {
str = strings.Replace(str, "http://", "", 1)
str = strings.Replace(str, "https://", "", 1)
str = TP + "" + str
- if !IsInStringArray(links, str) {
+ _ , isReply := IsReplyToOP(db, op, str)
+ if !IsInStringArray(links, str) && isReply {
links = append(links, str)
}
}
@@ -1721,26 +1818,34 @@ func GetActor(id string) Actor {
return respActor
}
- req, err := http.NewRequest("GET", id, nil)
+ actor, instance := GetActorInstance(id)
- CheckError(err, "error with getting actor req")
+ if ActorCache[actor + "@" + instance].Id != "" {
+ respActor = ActorCache[actor + "@" + instance]
+ } else {
+ req, err := http.NewRequest("GET", id, nil)
- req.Header.Set("Accept", activitystreams)
+ CheckError(err, "error with getting actor req")
- resp, err := RouteProxy(req)
+ req.Header.Set("Accept", activitystreams)
- if err != nil {
- fmt.Println("error with getting actor resp " + id)
- return respActor
- }
+ resp, err := RouteProxy(req)
- defer resp.Body.Close()
+ if err != nil {
+ fmt.Println("error with getting actor resp " + id)
+ return respActor
+ }
- body, _ := ioutil.ReadAll(resp.Body)
+ defer resp.Body.Close()
+
+ body, _ := ioutil.ReadAll(resp.Body)
+
+ err = json.Unmarshal(body, &respActor)
- err = json.Unmarshal(body, &respActor)
+ CheckError(err, "error getting actor from body")
- CheckError(err, "error getting actor from body")
+ ActorCache[actor + "@" + instance] = respActor
+ }
return respActor
}
@@ -1765,7 +1870,6 @@ func GetActorCollection(collection string) Collection {
return nCollection
}
-
defer resp.Body.Close()
if resp.StatusCode == 200 {
@@ -2076,7 +2180,9 @@ func MakeActivityRequest(db *sql.DB, activity Activity) {
_, err = RouteProxy(req)
- CheckError(err, "error with sending activity resp to")
+ if err != nil {
+ fmt.Println("error with sending activity resp to actor " + instance)
+ }
}
}
}
@@ -2304,7 +2410,7 @@ func UpdateObjectWithPreview(db *sql.DB, id string, preview string) {
func ParseCommentForReply(comment string) string {
- re := regexp.MustCompile("(>>)(https://|http://)?(www\\.)?.+\\/\\w+")
+ re := regexp.MustCompile(`(>>(https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/)(f[A-Za-z0-9_.\-~]+-)?([A-Za-z0-9_.\-~]+)?#?([A-Za-z0-9_.\-~]+)?)`)
match := re.FindAllStringSubmatch(comment, -1)
var links []string
@@ -2315,7 +2421,7 @@ func ParseCommentForReply(comment string) string {
}
if(len(links) > 0){
- _, isValid := CheckValidActivity(links[0])
+ _, isValid := CheckValidActivity(strings.ReplaceAll(links[0], ">", ""))
if(isValid) {
return links[0]
@@ -2489,21 +2595,30 @@ func CreatedNeededDirectories() {
//looks for actor with pattern of board@instance
func FingerActor(path string) Actor{
+ var nActor Actor
+
actor, instance := GetActorInstance(path)
- r := FingerRequest(actor, instance)
+ if actor == "" && instance == "" {
+ return nActor
+ }
- var nActor Actor
+ if ActorCache[actor + "@" + instance].Id != "" {
+ nActor = ActorCache[actor + "@" + instance]
+ } else {
+ r := FingerRequest(actor, instance)
+ if r != nil && r.StatusCode == 200 {
+ defer r.Body.Close()
+
+ body, _ := ioutil.ReadAll(r.Body)
- if r != nil && r.StatusCode == 200 {
- defer r.Body.Close()
-
- body, _ := ioutil.ReadAll(r.Body)
+ err := json.Unmarshal(body, &nActor)
- err := json.Unmarshal(body, &nActor)
+ CheckError(err, "error getting fingerrequet resp from json body")
- CheckError(err, "error getting fingerrequet resp from json body")
- }
+ ActorCache[actor + "@" + instance] = nActor
+ }
+ }
return nActor
}
@@ -2561,7 +2676,16 @@ func GetActorInstance(path string) (string, string) {
}
}
- re = regexp.MustCompile(`(https?:\\)?(www)?([\w\d-_.:]+)\/([\w\d-_.]+)(\/([\w\d-_.]+))?`)
+ re = regexp.MustCompile(`(https?://)(www)?([\w\d-_.:]+)(/|\s+|\r|\r\n)?$`)
+ mainActor := re.MatchString(path)
+ if(mainActor) {
+ match := re.FindStringSubmatch(path)
+ if(len(match) > 2) {
+ return "main", match[3]
+ }
+ }
+
+ re = regexp.MustCompile(`(https?://)?(www)?([\w\d-_.:]+)\/([\w\d-_.]+)(\/([\w\d-_.]+))?`)
httpFormat := re.MatchString(path)
if(httpFormat) {
@@ -2663,6 +2787,12 @@ func HashMedia(media string) string {
return hex.EncodeToString(h.Sum(nil))
}
+func HashBytes(media []byte) string {
+ h:= sha256.New()
+ h.Write(media)
+ return hex.EncodeToString(h.Sum(nil))
+}
+
func RouteImages(w http.ResponseWriter, media string) {
req, err := http.NewRequest("GET", MediaHashs[media], nil)
@@ -2720,3 +2850,54 @@ func HasValidation(w http.ResponseWriter, r *http.Request, actor Actor) bool {
return true
}
+
+func IsReplyToOP(db *sql.DB, op string, link string) (string, bool) {
+
+ if op == link {
+ return link, true
+ }
+
+ re := regexp.MustCompile(`f(\w+)\-`)
+ match := re.FindStringSubmatch(link)
+
+ if len(match) > 0 {
+ re := regexp.MustCompile(`(.+)\-`)
+ link = re.ReplaceAllString(link, "")
+ link = "%" + match[1] + "/" + link
+ }
+
+ query := `select id from replies where id like $1 and inreplyto=$2`
+
+ rows, err := db.Query(query, link, op)
+
+ CheckError(err, "error selecting in reply to op from db")
+
+ var id string
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&id)
+
+ if id != "" {
+
+ return id, true
+ }
+
+ return "", false
+}
+
+func GetReplyOP(db *sql.DB, link string) string {
+
+ query := `select id from replies where id in (select inreplyto from replies where id=$1) and inreplyto=''`
+
+ rows, err := db.Query(query, link)
+
+ CheckError(err, "could not get reply OP from db ")
+
+ var id string
+
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&id)
+
+ return id
+}