home timeline!
Anirudh Oppiliappan x@icyphox.sh
Fri, 12 Jul 2024 13:39:08 +0300
6 files changed,
167 insertions(+),
3 deletions(-)
M
database.go
→
database.go
@@ -249,7 +249,13 @@ return getsomehonks(rows, err)
} func gethonksforuser(userid UserID, wanted int64) []*Honk { dt := time.Now().Add(-honkwindow).UTC().Format(dbtimeformat) - rows, err := stmtHonksForUser.Query(wanted, userid, dt, userid, userid) + rows, err := stmtHonksForUser.Query(wanted, userid, dt, userid, userid, 250) + return getsomehonks(rows, err) +} + +func getlimitedhonksforuser(userid UserID, minid, maxid int64, limit int) []*Honk { + dt := time.Now().Add(-honkwindow).UTC().Format(dbtimeformat) + rows, err := stmtHonksForUserPrecise.Query(minid, maxid, userid, dt, userid, userid, limit) return getsomehonks(rows, err) } func gethonksforuserfirstclass(userid UserID, wanted int64) []*Honk {@@ -1292,6 +1298,7 @@ var stmtGetTracks *sql.Stmt
var stmtSaveChonk, stmtLoadChonks, stmtGetChatters *sql.Stmt var stmtDeliquentCheck, stmtDeliquentUpdate *sql.Stmt var stmtGetUserCount *sql.Stmt +var stmtHonksForUserPrecise *sql.Stmt var stmtGetActiveUserCount *sql.Stmt var stmtGetLocalHonkCount *sql.Stmt var stmtSaveMastoApp *sql.Stmt@@ -1345,6 +1352,7 @@ stmtNamedDubbers = preparetodie(db, "select honkerid, userid, name, xid, flavor from honkers where userid = ? and name = ? and flavor = 'dub'")
selecthonks := "select honks.honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, format, convoy, whofore, flags from honks join users on honks.userid = users.userid " limit := " order by honks.honkid desc limit 250" + customlimit := " order by honks.honkid desc limit ?" smalllimit := " order by honks.honkid desc limit ?" butnotthose := " and convoy not in (select name from zonkers where userid = ? and wherefore = 'zonvoy' order by zonkerid desc limit 100)" stmtOneXonk = preparetodie(db, selecthonks+"where honks.userid = ? and (xid = ? or url = ?)")@@ -1354,7 +1362,8 @@ stmtPublicHonks = preparetodie(db, selecthonks+"where whofore = 2 and dt > ?"+smalllimit)
stmtEventHonks = preparetodie(db, selecthonks+"where (whofore = 2 or honks.userid = ?) and what = 'event'"+smalllimit) stmtUserHonks = preparetodie(db, selecthonks+"where honks.honkid > ? and (whofore = 2 or whofore = ?) and username = ? and dt > ?"+smalllimit) myhonkers := " and honker in (select xid from honkers where userid = ? and (flavor = 'sub' or flavor = 'peep' or flavor = 'presub') and combos not like '% - %')" - stmtHonksForUser = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.userid = ? and dt > ?"+myhonkers+butnotthose+limit) + stmtHonksForUser = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.userid = ? and dt > ?"+myhonkers+butnotthose+customlimit) + stmtHonksForUserPrecise = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.honkid < ? and honks.userid = ? and dt > ?"+myhonkers+butnotthose+customlimit) stmtHonksForUserFirstClass = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.userid = ? and dt > ? and (rid = '' or what = 'bonk')"+myhonkers+butnotthose+limit) stmtHonksForMe = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.userid = ? and dt > ? and whofore = 1"+butnotthose+smalllimit) sqlHonksFromLongAgo = selecthonks + "where honks.honkid > ? and honks.userid = ? and (WHERECLAUSE) and (whofore = 2 or flags & 4)" + butnotthose + limit
M
flake.nix
→
flake.nix
@@ -71,7 +71,7 @@ };
docker = pkgs.dockerTools.buildLayeredImage { name = "sini:5000/honk"; tag = "latest"; - contents = [ files honk pkgs.cacert ]; + contents = [ files honk pkgs.cacert pkgs.bashInteractive pkgs.coreutils pkgs.sqlite ]; config = { Entrypoint = [ "${honk}/bin/honk" ]; ExposedPorts = { "5555/tcp" = { }; };@@ -86,9 +86,13 @@ pkgs = nixpkgsFor.${system};
in { default = pkgs.mkShell { + buildInputs = [ pkgs.sqlite ]; nativeBuildInputs = with pkgs; [ go + gcc ]; + CGO_ENABLED = 1; + CC = "${pkgs.gcc}/bin/gcc"; }; }); };
M
masto.go
→
masto.go
@@ -1,11 +1,13 @@
package main import ( + "bytes" "database/sql" "fmt" "log" "net/http" "slices" + "strconv" "strings" "time"@@ -324,3 +326,69 @@ log.Println(j.ToString())
goodjunk(rw, j) } + +// https://docs.joinmastodon.org/methods/timelines/#home +func hometimeline(rw http.ResponseWriter, r *http.Request) { + limit := r.URL.Query().Get("limit") + minid := r.URL.Query().Get("min_id") + maxid := r.URL.Query().Get("max_id") + + dlog.Println("limit", limit, "minid", minid, "maxid", maxid) + + var ( + minidInt int + maxidInt int + limitInt int + err error + ) + + list := []junk.Junk{} + me, ok := somenumberedusers.Get(UserID(1)) + if !ok { + elog.Fatalf("masto: no user number 1???") + } + + if limit == "" { + limit = "5" + } + limitInt, _ = strconv.Atoi(limit) + + if minid != "" { + minidInt, err = strconv.Atoi(minid) + if err != nil { + elog.Printf("masto: invalid min_id: %s: %s", minid, err) + http.Error(rw, "invalid min_id", http.StatusBadRequest) + return + } + } + if maxid != "" { + maxidInt, err = strconv.Atoi(maxid) + if err != nil { + elog.Printf("masto: invalid max_id: %s: %s", minid, err) + http.Error(rw, "invalid max_id", http.StatusBadRequest) + return + } + } + + honks := getlimitedhonksforuser(me.ID, int64(minidInt), int64(maxidInt), limitInt) + reverbolate(me.ID, honks) + for _, h := range honks { + hj := honktomasto(h) + if hj == nil { + elog.Printf("masto: failed to convert honk %d to masto", h.ID) + http.Error(rw, "failed to convert honk", http.StatusInternalServerError) + } + list = append(list, hj) + } + + buf := bytes.Buffer{} + err = listjunk(&buf, list) + if err != nil { + elog.Println(err) + http.Error(rw, "error encoding json", http.StatusInternalServerError) + } + + rw.Header().Set("Content-Type", "application/json; charset=utf-8") + rw.WriteHeader(http.StatusOK) + rw.Write(buf.Bytes()) +}
M
masto_util.go
→
masto_util.go
@@ -2,7 +2,9 @@ package main
import ( "crypto/rand" + "encoding/json" "fmt" + "io" "net/http" "time"@@ -50,3 +52,82 @@ b := make([]byte, 32)
rand.Read(b) return fmt.Sprintf("%x", b) } + +func listjunk(w io.Writer, j []junk.Junk) error { + e := json.NewEncoder(w) + e.SetEscapeHTML(false) + e.SetIndent("", " ") + return e.Encode(j) +} + +func honktomasto(h *Honk) junk.Junk { + j := junk.Junk{} + + j["id"] = fmt.Sprintf("%d", h.ID) + j["created_at"] = h.Date.Format("2006-01-02T15:04:05.000Z07:00") + j["sensitive"] = false + j["spoiler_text"] = "" + j["visibility"] = "public" + j["language"] = "en" + j["uri"] = h.URL + j["url"] = h.URL + j["replies_count"] = len(h.Replies) + j["reblogs_count"] = 0 + j["favourites_count"] = 0 + j["reblogged"] = false + j["favourited"] = false + j["muted"] = false + j["bookmarked"] = false + j["content"] = h.HTML + j["account"] = junk.Junk{ + "id": "2019", + "username": h.Username, + "acct": h.Handle, + "display_name": h.Username, + "avatar": "https://h.icyphox.sh/a?a=foo", + "avatar_static": "https://h.icyphox.sh/a?a=foo", + "header": "https://h.icyphox.sh/meme/banner.jpg", + "header_static": "https://h.icyphox.sh/meme/banner.jpg", + "note": "foo bar baz", + "url": h.Honker, + "emojis": []junk.Junk{}, + "fields": []junk.Junk{}, + "bot": false, + "last_status_at": "", + "discoverable": false, + "source": nil, + "created_at": "", + "statuses_count": 0, + "indexable": false, + "group": false, + "locked": false, + "followers_count": 0, + "following_count": 0, + } + + j["card"] = nil + j["reblog"] = nil + j["media_attachments"] = []junk.Junk{} + j["tags"] = []junk.Junk{} + j["emojis"] = []junk.Junk{} + j["edited_at"] = nil + j["poll"] = nil + j["mentions"] = []junk.Junk{} + j["in_reply_to_id"] = nil + j["in_reply_to_account_id"] = nil + + if h.Replies != nil { + for _, r := range h.Replies { + j["mentions"] = append(j["mentions"].([]junk.Junk), junk.Junk{ + "id": r.ID, + "url": r.URL, + "username": r.Username, + "acct": r.Handle, + }) + j["in_reply_to_id"] = r.ID + j["in_reply_to_account_id"] = nil + } + } + + return j +}
M
web.go
→
web.go
@@ -3243,6 +3243,7 @@ mastopost.HandleFunc("/oauth/token", oauthtoken)
mastoget.HandleFunc("/api/v1/instance", instance) mastopost.HandleFunc("/api/v1/apps", apiapps) mastoget.HandleFunc("/api/v1/accounts/verify_credentials", checktoken(verifycreds)) + mastoget.HandleFunc("/api/v1/timelines/home", checktoken(hometimeline)) loggedmux := handlers.LoggingHandler(os.Stdout, mux) err = http.Serve(listener, loggedmux)