diff options
| author | Xe Iaso <me@xeiaso.net> | 2023-06-19 21:59:53 -0400 |
|---|---|---|
| committer | Xe Iaso <me@xeiaso.net> | 2023-06-19 21:59:53 -0400 |
| commit | 60264ef896ea876456ea3168882049405c3ed38d (patch) | |
| tree | ba1b981372b31af09d4e5cf292f707da28355663 | |
| parent | 390f313d38a39be9876176eed4b2a50c11657b1e (diff) | |
| download | x-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.go | 12 | ||||
| -rw-r--r-- | cmd/xatci/main.go | 172 | ||||
| -rw-r--r-- | go.mod | 11 | ||||
| -rw-r--r-- | go.sum | 30 | ||||
| -rw-r--r-- | gomod2nix.toml | 33 | ||||
| -rw-r--r-- | web/marginalia/marginalia.go | 95 | ||||
| -rw-r--r-- | web/nodeinfo/nodeinfo.go | 2 | ||||
| -rw-r--r-- | web/openai/chatgpt/chatgpt.go | 9 |
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() +} @@ -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 @@ -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 { |
