aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2023-06-19 21:59:53 -0400
committerXe Iaso <me@xeiaso.net>2023-06-19 21:59:53 -0400
commit60264ef896ea876456ea3168882049405c3ed38d (patch)
treeba1b981372b31af09d4e5cf292f707da28355663
parent390f313d38a39be9876176eed4b2a50c11657b1e (diff)
downloadx-60264ef896ea876456ea3168882049405c3ed38d.tar.xz
x-60264ef896ea876456ea3168882049405c3ed38d.zip
cmd: add new command xatci
Signed-off-by: Xe Iaso <me@xeiaso.net>
-rw-r--r--cmd/marabot/discord.go12
-rw-r--r--cmd/xatci/main.go172
-rw-r--r--go.mod11
-rw-r--r--go.sum30
-rw-r--r--gomod2nix.toml33
-rw-r--r--web/marginalia/marginalia.go95
-rw-r--r--web/nodeinfo/nodeinfo.go2
-rw-r--r--web/openai/chatgpt/chatgpt.go9
8 files changed, 355 insertions, 9 deletions
diff --git a/cmd/marabot/discord.go b/cmd/marabot/discord.go
index a1e16c5..b34eb1e 100644
--- a/cmd/marabot/discord.go
+++ b/cmd/marabot/discord.go
@@ -77,10 +77,16 @@ func (mr *MaraRevolt) DiscordMessageDelete(s *discordgo.Session, m *discordgo.Me
ln.Error(ctx, err, ln.Action("nuking deleted messages"))
}
- row := mr.db.QueryRowContext(ctx, "SELECT id FROM s3_uploads WHERE message_id = ?", m.ID)
- if row.Err() == nil {
+ rows, err := mr.db.QueryContext(ctx, "SELECT id FROM s3_uploads WHERE message_id = ?", m.ID)
+ if err != nil {
+ ln.Error(ctx, err)
+ return
+ }
+ defer rows.Close()
+
+ for rows.Next() {
var id string
- if err := row.Scan(&id); err != nil {
+ if err := rows.Scan(&id); err != nil {
ln.Error(ctx, err)
return
}
diff --git a/cmd/xatci/main.go b/cmd/xatci/main.go
new file mode 100644
index 0000000..6cdb50d
--- /dev/null
+++ b/cmd/xatci/main.go
@@ -0,0 +1,172 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/aws/aws-sdk-go/aws"
+ "github.com/go-shiori/go-readability"
+ "github.com/mymmrac/telego"
+ th "github.com/mymmrac/telego/telegohandler"
+ tu "github.com/mymmrac/telego/telegoutil"
+ "within.website/ln"
+ "within.website/ln/opname"
+ "within.website/x/internal"
+ "within.website/x/web/marginalia"
+ "within.website/x/web/openai/chatgpt"
+)
+
+var (
+ marginaliaToken = flag.String("marginalia-token", "", "Token for Marginalia internet search")
+ openAIToken = flag.String("openai-token", "", "OpenAI token")
+ openAIModel = flag.String("openai-model", "gpt-3.5-turbo-16k-0613", "OpenAI model to use")
+ telegramAdmin = flag.Int64("telegram-admin", 0, "Telegram bot admin")
+ telegramToken = flag.String("telegram-token", "", "Telegram bot token")
+)
+
+func main() {
+ internal.HandleStartup()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ ctx = opname.With(ctx, "xatci")
+
+ mc := marginalia.New(*marginaliaToken, nil)
+
+ cGPT := chatgpt.NewClient(*openAIToken)
+
+ // Note: Please keep in mind that default logger may expose sensitive information,
+ // use in development only
+ bot, err := telego.NewBot(*telegramToken)
+ if err != nil {
+ ln.FatalErr(ctx, err)
+ }
+
+ // Get updates channel
+ updates, err := bot.UpdatesViaLongPolling(nil)
+ if err != nil {
+ ln.FatalErr(ctx, err)
+ }
+
+ // Create bot handler and specify from where to get updates
+ bh, err := th.NewBotHandler(bot, updates)
+ if err != nil {
+ ln.FatalErr(ctx, err)
+ }
+
+ // Stop handling updates
+ defer bh.Stop()
+
+ // Stop getting updates
+ defer bot.StopLongPolling()
+
+ // Register new handler with match on command `/start`
+ bh.Handle(func(bot *telego.Bot, update telego.Update) {
+ // Send message
+ if _, err := bot.SendMessage(tu.Message(
+ tu.ID(update.Message.Chat.ID),
+ fmt.Sprintf("Hello %s!", update.Message.From.FirstName),
+ )); err != nil {
+ ln.Error(ctx, err)
+ }
+ }, th.CommandEqual("start"))
+
+ bh.Handle(func(bot *telego.Bot, update telego.Update) {
+ if update.Message.From.ID != *telegramAdmin {
+ bot.SendMessage(tu.Message(
+ tu.ID(update.Message.Chat.ID),
+ "unknown command",
+ ))
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
+ defer cancel()
+ ctx = opname.With(ctx, "xatci.marginalia.search")
+
+ q := strings.Join(strings.Split(update.Message.Text, " ")[1:], " ")
+
+ ctx = ln.WithF(ctx, ln.F{
+ "telegram_requestor": update.Message.From.ID,
+ "telegram_requestor_name": fmt.Sprintf("%s %s", update.Message.From.FirstName, update.Message.From.LastName),
+ "search_query": q,
+ })
+
+ results, err := mc.Search(ctx, &marginalia.Request{
+ Query: q,
+ Count: aws.Int(5),
+ })
+ if err != nil {
+ ln.Error(ctx, err)
+ bot.SendMessage(tu.Message(
+ tu.ID(update.Message.Chat.ID),
+ fmt.Sprintf("Error: %v", err),
+ ))
+ return
+ }
+
+ var sb strings.Builder
+
+ fmt.Fprintf(&sb, "License: %s\n\n", results.License)
+
+ for _, result := range results.Results {
+ fmt.Fprintf(&sb, "**%s** (%s):\n", result.Title, result.URL)
+
+ ln.Log(ctx, ln.Action("resolving article"), ln.F{
+ "result_title": result.Title,
+ "result_url": result.URL,
+ })
+
+ article, err := readability.FromURL(result.URL, 30*time.Second)
+ if err != nil {
+ fmt.Fprintf(&sb, "Can't parse article: %v", err)
+ continue
+ }
+
+ resp, err := cGPT.Complete(ctx, chatgpt.Request{
+ Model: *openAIModel,
+ Messages: []chatgpt.Message{
+ {
+ Role: "system",
+ Content: "You are a programmer's research assistant, engaging users in thoughtful discussions on a wide range of topics, from ethics and metaphysics to programming and architectural design. Offer insights into the works of various philosophers, well-known programmers, their theories, and ideas. Encourage users to think critically and reflect on the nature of existence, knowledge, and values.",
+ },
+ {
+ Role: "user",
+ Content: "Can you summarize this article by " + article.Byline + " in 3 sentences or less?\n\n" + article.TextContent,
+ },
+ },
+ })
+ if err != nil {
+ ln.Error(ctx, err)
+ }
+
+ fmt.Fprintf(&sb, "%s\n\n", resp.Choices[0].Message.Content)
+ }
+
+ msg := tu.Message(tu.ID(update.Message.Chat.ID), sb.String())
+ msg.ParseMode = telego.ModeMarkdown
+
+ if _, err := bot.SendMessage(msg); err != nil {
+ ln.Error(ctx, err)
+ return
+ }
+
+ ln.Log(ctx, ln.Action("query successful"))
+ }, th.CommandEqual("search"))
+
+ // Register new handler with match on any command
+ // Handlers will match only once and in order of registration,
+ // so this handler will be called on any command except `/start` command
+ bh.Handle(func(bot *telego.Bot, update telego.Update) {
+ // Send message
+ _, _ = bot.SendMessage(tu.Message(
+ tu.ID(update.Message.Chat.ID),
+ "Unknown command, use /start",
+ ))
+ }, th.AnyCommand())
+
+ // Start handling updates
+ bh.Start()
+}
diff --git a/go.mod b/go.mod
index aa6789d..485f2ab 100644
--- a/go.mod
+++ b/go.mod
@@ -46,9 +46,20 @@ require (
)
require (
+ github.com/andybalholm/brotli v1.0.5 // indirect
+ github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
+ github.com/fasthttp/router v1.4.19 // indirect
+ github.com/go-shiori/dom v0.0.0-20210627111528-4e4722cd0d65 // indirect
+ github.com/go-shiori/go-readability v0.0.0-20230421032831-c66949dfc0ad // indirect
+ github.com/goccy/go-json v0.10.2 // indirect
+ github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
+ github.com/mymmrac/telego v0.25.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
+ github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.47.0 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
diff --git a/go.sum b/go.sum
index e1afdbb..aad8676 100644
--- a/go.sum
+++ b/go.sum
@@ -71,6 +71,11 @@ github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A=
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw=
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
+github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
+github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY=
+github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
+github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/aws/aws-sdk-go v1.44.284 h1:Oc5Kubi43/VCkerlt3ZU3KpBju6BpNkoG3s7E8vj/O8=
@@ -163,6 +168,8 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojt
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y=
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
+github.com/fasthttp/router v1.4.19 h1:RLE539IU/S4kfb4MP56zgP0TIBU9kEg0ID9GpWO0vqk=
+github.com/fasthttp/router v1.4.19/go.mod h1:+Fh3YOd8x1+he6ZS+d2iUDBH9MGGZ1xQFUor0DE9rKE=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fogleman/primitive v0.0.0-20190214200932-673f57e7b1b5 h1:/oy2PBMZq4jeEfqM5OCuvWYu+6yZEb0SSPbwL1fCaXw=
@@ -191,14 +198,23 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
+github.com/go-shiori/dom v0.0.0-20210627111528-4e4722cd0d65 h1:zx4B0AiwqKDQq+AgqxWeHwbbLJQeidq20hgfP+aMNWI=
+github.com/go-shiori/dom v0.0.0-20210627111528-4e4722cd0d65/go.mod h1:NPO1+buE6TYOWhUI98/hXLHHJhunIpXRuvDN4xjkCoE=
+github.com/go-shiori/go-readability v0.0.0-20230421032831-c66949dfc0ad h1:3VP5Q8Mh165h2DHmXWFT4LJlwwvgTRlEuoe2vnsVnJ4=
+github.com/go-shiori/go-readability v0.0.0-20230421032831-c66949dfc0ad/go.mod h1:2DpZlTJO/ycxp/vsc/C11oUyveStOgIXB88SYV1lncI=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
+github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
+github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -382,6 +398,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/mymmrac/telego v0.25.0 h1:ANI4irLey+bQC8UEDB/d7JZrGmxWmcuhMMrtyLEEzI4=
+github.com/mymmrac/telego v0.25.0/go.mod h1:UGyuLaO49ZgiWLiHuB5rotF6Ms7Tv9tu2R3LTxnTmSc=
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
@@ -437,6 +455,8 @@ github.com/samber/go-gpt-3-encoder v0.3.1 h1:YWb9GsGYUgSX/wPtsEHjyNGRQXsQ9vDCg9S
github.com/samber/go-gpt-3-encoder v0.3.1/go.mod h1:27nvdvk9ZtALyNtgs9JsPCMYja0Eleow/XzgjqwRtLU=
github.com/samber/lo v1.37.0 h1:XjVcB8g6tgUp8rsPsJ2CvhClfImrpL04YpQHXeHPhRw=
github.com/samber/lo v1.37.0/go.mod h1:9vaz2O4o8oOnK23pd2TrXufcbdbJIa3b6cstBWKpopA=
+github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
+github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a h1:iLcLb5Fwwz7g/DLK89F+uQBDeAhHhwdzB5fSlVdhGcM=
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a/go.mod h1:wozgYq9WEBQBaIJe4YZ0qTSFAMxmcwBhQH0fO0R34Z0=
github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0=
@@ -451,6 +471,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d h1:K3j02b5j2Iw1xoggN9B2DIEkhWGheqFOeDkdJdBrJI8=
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d/go.mod h1:2P+hpOwd53e7JMX/L4f3VXkv1G+33ES6IWZSrkIeWNs=
github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 h1:pBpqbsyX9H8c26oPYC2H+232HOdp1gDnCztoKmKWKDA=
@@ -477,6 +498,10 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c=
+github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89/go.mod h1:ejwOYCjnDMyO5LXFXRARQJGBZ6xQJZ3rgAHE5drSuMM=
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
@@ -561,6 +586,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -597,6 +623,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210505214959-0714010a04ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
@@ -609,6 +636,7 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.0.0-20220921203646-d300de134e69/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -722,12 +750,14 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/gomod2nix.toml b/gomod2nix.toml
index 2e7cf57..a722e5d 100644
--- a/gomod2nix.toml
+++ b/gomod2nix.toml
@@ -19,6 +19,12 @@ schema = 3
[mod."github.com/alexbrainman/sspi"]
version = "v0.0.0-20210105120005-909beea2cc74"
hash = "sha256-sMY9gSeRWqKE0JwY4HbUF1KO9eaL/hQ/A/uoyr0hrQI="
+ [mod."github.com/andybalholm/brotli"]
+ version = "v1.0.5"
+ hash = "sha256-/qS8wU8yZQJ+uTOg66rEl9s7spxq9VIXF5L1BcaEClc="
+ [mod."github.com/andybalholm/cascadia"]
+ version = "v1.3.2"
+ hash = "sha256-Nc9SkqJO/ecincVcUBFITy24TMmMGj5o0Q8EgdNhrEk="
[mod."github.com/aws/aws-sdk-go"]
version = "v1.44.284"
hash = "sha256-e0vxPOXFBc9i2EKoxowM1N+b9v1+AsQaVXuSUW7rdPQ="
@@ -100,6 +106,9 @@ schema = 3
[mod."github.com/facebookgo/subset"]
version = "v0.0.0-20150612182917-8dac2c3c4870"
hash = "sha256-Ub0cBFwF6MBzTZ7fpqxrC375arBv+au5I/LLzksVzE8="
+ [mod."github.com/fasthttp/router"]
+ version = "v1.4.19"
+ hash = "sha256-RFDvVYSGI5vHdhGnso5kRE3neX9Xeo/rn1+ngvsls7Q="
[mod."github.com/fogleman/gg"]
version = "v1.3.0"
hash = "sha256-Fs2JI0FmF4N5EzXJzGAPZMxZxo6wKyebkN/iBZ9sdNo="
@@ -115,9 +124,21 @@ schema = 3
[mod."github.com/go-ole/go-ole"]
version = "v1.2.6"
hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs="
+ [mod."github.com/go-shiori/dom"]
+ version = "v0.0.0-20210627111528-4e4722cd0d65"
+ hash = "sha256-kHoG7/v+Uc1DMLL0UcIDk2rFpujVv5RTMy4BkyRNjs0="
+ [mod."github.com/go-shiori/go-readability"]
+ version = "v0.0.0-20230421032831-c66949dfc0ad"
+ hash = "sha256-67CfGKvCghUq+1XMcAMF+O9xsbQNkwma4L9cxA4pLtw="
+ [mod."github.com/goccy/go-json"]
+ version = "v0.10.2"
+ hash = "sha256-6fMD2/Rku8HT0zDdeA23pX0YxbohiIOC8OJNYbylJTQ="
[mod."github.com/godbus/dbus/v5"]
version = "v5.1.0"
hash = "sha256-xOCMJpQK3KTmHTPn/CdqI4j0eENCtMmJDgAIoYqYOEY="
+ [mod."github.com/gogs/chardet"]
+ version = "v0.0.0-20211120154057-b7413eaefb8f"
+ hash = "sha256-4MeqBJsh4U+ZEbfdDwdciTYMlQWkCil2KJbUxHjBSIo="
[mod."github.com/golang/freetype"]
version = "v0.0.0-20170609003504-e2365dfdc4a0"
hash = "sha256-AHAFBd20/tqxohkWyQkui2bUef9i1HWYgk9LOIFErvA="
@@ -226,6 +247,9 @@ schema = 3
[mod."github.com/mndrix/ps"]
version = "v0.0.0-20170330174427-18e65badd6ab"
hash = "sha256-Q9skxtyqOwkBxmUnzNCfbn813vPbqvwuAihwq/wkKs4="
+ [mod."github.com/mymmrac/telego"]
+ version = "v0.25.0"
+ hash = "sha256-fWfHuTzvIOW3qoM1oTMF+kUD9C5s5+TBREkvP6Vxmfo="
[mod."github.com/oklog/ulid/v2"]
version = "v2.1.0"
hash = "sha256-/oQPgcO1xKbHXutxz0WPfIduShPrfH1l+7/mj8jLst8="
@@ -286,6 +310,9 @@ schema = 3
[mod."github.com/samber/lo"]
version = "v1.37.0"
hash = "sha256-5m0advnk/wy/bFygNyxaPVX2PgA5oF1lSHP71hAOhCc="
+ [mod."github.com/savsgio/gotils"]
+ version = "v0.0.0-20230208104028-c358bd845dee"
+ hash = "sha256-38uPEruTtVRqleBivVwx6oO1FSx4edqEujYdZNTriMo="
[mod."github.com/sebest/xff"]
version = "v0.0.0-20210106013422-671bd2870b3a"
hash = "sha256-t7Gdp7S71Koej5Njg3jOo5vwyj02tJCbJjrq/vZGOho="
@@ -325,6 +352,12 @@ schema = 3
[mod."github.com/u-root/uio"]
version = "v0.0.0-20230305220412-3e8cd9d6bf63"
hash = "sha256-y0VT9PLROozi6wNMgnX706ifumQxlMc8y4/XZDhdfMY="
+ [mod."github.com/valyala/bytebufferpool"]
+ version = "v1.0.0"
+ hash = "sha256-I9FPZ3kCNRB+o0dpMwBnwZ35Fj9+ThvITn8a3Jr8mAY="
+ [mod."github.com/valyala/fasthttp"]
+ version = "v1.47.0"
+ hash = "sha256-7jeGnEnQi6s60bSGkUHWA7rt39FTEghSJLt+rGPk3og="
[mod."github.com/vishvananda/netlink"]
version = "v1.2.1-beta.2"
hash = "sha256-ePReedgYT0KuAx/HOUgG76zDZ2XpW/u8bGlsWysxKzE="
diff --git a/web/marginalia/marginalia.go b/web/marginalia/marginalia.go
new file mode 100644
index 0000000..efa4e83
--- /dev/null
+++ b/web/marginalia/marginalia.go
@@ -0,0 +1,95 @@
+// Package marginalia implements the Marginalia search API.
+//
+// You need an API key to use this. See the Marginalia API docs for more information: https://www.marginalia.nu/marginalia-search/api/
+package marginalia
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+
+ "within.website/x/web"
+)
+
+type Request struct {
+ Query string
+ Count *int
+ Index *int
+}
+
+type Response struct {
+ License string `json:"license"`
+ Query string `json:"query"`
+ Results []Result `json:"results"`
+}
+
+type Result struct {
+ URL string `json:"url"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Quality float64 `json:"quality"`
+ Details [][]Detail `json:"details"`
+}
+
+type Detail struct {
+ Keyword string `json:"keyword"`
+ Count int `json:"count"`
+ FlagsUnstableAPI []string `json:"flagsUnstableAPI"`
+}
+
+type Client struct {
+ apiKey string
+ httpCli *http.Client
+}
+
+func New(apiKey string, httpCli *http.Client) *Client {
+ if httpCli == nil {
+ httpCli = &http.Client{}
+ }
+
+ return &Client{
+ apiKey: apiKey,
+ httpCli: httpCli,
+ }
+}
+
+func (c *Client) Search(ctx context.Context, req *Request) (*Response, error) {
+ u, err := url.Parse("https://api.marginalia.nu/")
+ if err != nil {
+ return nil, err
+ }
+ u.Path = "/" + c.apiKey + "/search/" + url.QueryEscape(req.Query)
+ q := u.Query()
+ if req.Count != nil {
+ q.Set("count", fmt.Sprint(*req.Count))
+ }
+ if req.Index != nil {
+ q.Set("index", fmt.Sprint(*req.Index))
+ }
+ u.RawQuery = q.Encode()
+
+ r, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := c.httpCli.Do(r)
+ if err != nil {
+ return nil, err
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ return nil, web.NewError(http.StatusOK, resp)
+ }
+
+ defer resp.Body.Close()
+
+ var result Response
+ if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
+ return nil, err
+ }
+
+ return &result, nil
+}
diff --git a/web/nodeinfo/nodeinfo.go b/web/nodeinfo/nodeinfo.go
index 7c77c0e..2ab34ce 100644
--- a/web/nodeinfo/nodeinfo.go
+++ b/web/nodeinfo/nodeinfo.go
@@ -140,7 +140,7 @@ func FetchWithClient(ctx context.Context, cli *http.Client, nodeURL string) (*No
// Fetch uses the standard library HTTP client to fetch node information.
func Fetch(ctx context.Context, nodeURL string) (*Node, error) {
cli := &http.Client{
- Transport: useragent.Transport("github.com/Xe/x/web/nodeinfo", "https://within.website/.x.botinfo", http.DefaultTransport),
+ Transport: useragent.Transport("within.website/x/web/nodeinfo", "https://within.website/.x.botinfo", http.DefaultTransport),
}
return FetchWithClient(ctx, cli, nodeURL)
}
diff --git a/web/openai/chatgpt/chatgpt.go b/web/openai/chatgpt/chatgpt.go
index aab4ce7..9fb2d09 100644
--- a/web/openai/chatgpt/chatgpt.go
+++ b/web/openai/chatgpt/chatgpt.go
@@ -13,10 +13,9 @@ import (
)
type Request struct {
- Model string `json:"model"`
- Messages []Message `json:"messages"`
- Functions []Function `json:"functions,omitempty"`
- FunctionCall string `json:"function_call"`
+ Model string `json:"model"`
+ Messages []Message `json:"messages"`
+ Functions []Function `json:"functions,omitempty"`
}
type Function struct {
@@ -36,7 +35,7 @@ type Param struct {
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
- FunctionCall *Funcall `json:"function_call"`
+ FunctionCall *Funcall `json:"function_call,omitempty"`
}
type Funcall struct {