aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2024-09-07 11:46:50 -0400
committerXe Iaso <me@xeiaso.net>2024-09-07 11:46:50 -0400
commita96c8927da0fff4b2c1fd7ef7237cbaac3936ebf (patch)
treeefafff42b7bc221c719f312f52551a1eb7790222 /cmd
parent66d7530ad42d1575719d55b7d26ba763ece3aa30 (diff)
downloadx-a96c8927da0fff4b2c1fd7ef7237cbaac3936ebf.tar.xz
x-a96c8927da0fff4b2c1fd7ef7237cbaac3936ebf.zip
cmd: delete some old code
Signed-off-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/aegis/aegis.txt26
-rw-r--r--cmd/aegis/main.go63
-rw-r--r--cmd/arsene-analysis/.gitignore2
-rw-r--r--cmd/arsene-analysis/main.go155
-rw-r--r--cmd/eq/main.go60
-rw-r--r--cmd/ff-primitive/main.go56
-rw-r--r--cmd/relayd/main.go77
-rw-r--r--cmd/robocadey2/fly.toml26
-rw-r--r--cmd/robocadey2/main.go246
-rw-r--r--cmd/robocadey2/run.sh6
-rw-r--r--cmd/robocadey2/yeetfile.js4
-rw-r--r--cmd/xatci/main.go217
12 files changed, 0 insertions, 938 deletions
diff --git a/cmd/aegis/aegis.txt b/cmd/aegis/aegis.txt
deleted file mode 100644
index 24624ab..0000000
--- a/cmd/aegis/aegis.txt
+++ /dev/null
@@ -1,26 +0,0 @@
- =:::::::::~~~=
- :,:::::::,,::=
- = +++++ + ++=
- :~+~~~~~~~====
- :=+=~~~~~~=~~=
- =~:===~~~~~=~~!=
- =::~====~~~~=::::=
- =: ++====~~~~==::=
- =: -=+====~~~~~=~=
- =~= ~++===~~~~=,~=
- =~ +++==~~=:=~+=
- ,= +++==~~=~++
- := +++=+=~=~++
- ,= ++++==~==++
- ,~ ++++==~=+++
- ,~ +++===~~==+
- ,= ++====~~=++
- ,= +==~===~==+
- ,=+======~~==+
- :=+=~~~~~~~=++
- :===~~~~~~~+==
- :~===~~~~~~=+=
- ,~=~~~~~~~~===
- ,~=~~~~~~~~+=~
- ::+========+~=
- +=~~~~~~~~~~~=
diff --git a/cmd/aegis/main.go b/cmd/aegis/main.go
deleted file mode 100644
index a6a2005..0000000
--- a/cmd/aegis/main.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package main
-
-import (
- _ "embed"
- "flag"
- "fmt"
- "log"
- "net"
- "net/http"
- "net/http/httputil"
- "os"
- "path"
- "path/filepath"
-)
-
-var (
- hostport = flag.String("hostport", "[::]:31337", "TCP host:port to listen on")
- sockdir = flag.String("sockdir", "./run", "directory full of unix sockets to monitor")
-)
-
-//go:embed "aegis.txt"
-var core string
-
-func main() {
- flag.Parse()
-
- fmt.Print(core)
- log.SetFlags(0)
- log.Printf("%s -> %s", *hostport, *sockdir)
-
- http.DefaultServeMux.HandleFunc("/", proxyToUnixSocket)
-
- log.Fatal(http.ListenAndServe(*hostport, nil))
-}
-
-func proxyToUnixSocket(w http.ResponseWriter, r *http.Request) {
- name := path.Base(r.URL.Path)
-
- fname := filepath.Join(*sockdir, name+".sock")
- _, err := os.Stat(fname)
- if os.IsNotExist(err) {
- http.NotFound(w, r)
- return
- }
-
- ts := &http.Transport{
- Dial: func(_, _ string) (net.Conn, error) {
- return net.Dial("unix", fname)
- },
- DisableKeepAlives: true,
- }
-
- rp := httputil.ReverseProxy{
- Director: func(req *http.Request) {
- req.URL.Scheme = "http"
- req.URL.Host = "aegis"
- req.URL.Path = "/metrics"
- req.URL.RawPath = "/metrics"
- },
- Transport: ts,
- }
- rp.ServeHTTP(w, r)
-}
diff --git a/cmd/arsene-analysis/.gitignore b/cmd/arsene-analysis/.gitignore
deleted file mode 100644
index 29a7166..0000000
--- a/cmd/arsene-analysis/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.csv
-
diff --git a/cmd/arsene-analysis/main.go b/cmd/arsene-analysis/main.go
deleted file mode 100644
index 7cc90b9..0000000
--- a/cmd/arsene-analysis/main.go
+++ /dev/null
@@ -1,155 +0,0 @@
-package main
-
-import (
- "context"
- "encoding/csv"
- "flag"
- "fmt"
- "log"
- "log/slog"
- "os"
- "strconv"
- "time"
-
- "within.website/x/internal"
- "within.website/x/web/ollama"
-)
-
-var (
- foutName = flag.String("out", "enriched.csv", "output file name")
- ollamaHost = flag.String("ollama-host", "http://xe-inference.flycast", "ollama host")
- ollamaModel = flag.String("ollama-model", "nous-hermes2-mixtral:8x7b-dpo-q5_K_M", "ollama model")
- subsetFile = flag.String("subset", "", "subset CSV file to use")
-)
-
-type sentimentResponse struct {
- Sentiment string `json:"sentiment"`
-}
-
-func (sr sentimentResponse) Valid() error {
- if sr.Sentiment != "positive" && sr.Sentiment != "negative" && sr.Sentiment != "neutral" {
- return fmt.Errorf("invalid sentiment %q", sr.Sentiment)
- }
-
- return nil
-}
-
-func main() {
- internal.HandleStartup()
-
- fin, err := os.Open(*subsetFile)
- if err != nil {
- log.Fatal(err)
- }
- defer fin.Close()
-
- fout, err := os.Create(*foutName)
- if err != nil {
- log.Fatal(err)
- }
- defer fout.Close()
-
- w := csv.NewWriter(fout)
- w.Write([]string{"id", "price_change", "sentiment"})
-
- cli := ollama.NewClient(*ollamaHost)
-
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Hour)
- defer cancel()
-
- r := csv.NewReader(fin)
- for {
- row, err := r.Read()
- if err != nil {
- break
- }
-
- //slog.Debug("got", "row", row)
-
- sr, err := ParseSubsetRow(row)
- if err != nil {
- slog.Error("failed to parse row", "err", err)
- continue
- }
-
- sen, err := ollama.Hallucinate[sentimentResponse](ctx, cli, ollama.HallucinateOpts{
- Model: *ollamaModel,
- Messages: []ollama.Message{
- {
- Role: "system",
- Content: `Rate the sentiment of the following text. If the sentiment is positive, return this JSON object:
-{"sentiment":"positive"}
-If the sentiment is negative, return this JSON object:
-{"sentiment":"negative"}
-If there is neither a positive nor a negative sentiment, return this JSON object:
-{"sentiment":"neutral"}
-DO NOT send any whitespace or newlines in the JSON object.`,
- },
- {
- Role: "user",
- Content: sr.Body,
- },
- },
- })
- if err != nil {
- slog.Error("failed to chat", "err", err)
- continue
- }
-
- priceChange := ""
-
- if sr.PrevPrice > sr.AfterPrice {
- priceChange = "negative"
- } else if sr.PrevPrice < sr.AfterPrice {
- priceChange = "positive"
- } else {
- priceChange = "neutral"
- }
-
- w.Write([]string{
- strconv.Itoa(sr.ID),
- priceChange,
- sen.Sentiment,
- })
- w.Flush()
- }
-
- w.Flush()
-}
-
-type SubsetRow struct {
- ID int `json:"id"`
- Title string `json:"title"`
- Body string `json:"body"`
- PrevPrice float64 `json:"prev_price"`
- AfterPrice float64 `json:"after_price"`
-}
-
-func ParseSubsetRow(data []string) (*SubsetRow, error) {
- if len(data) != 5 {
- return nil, fmt.Errorf("expected 5 fields, got %d", len(data))
- }
-
- id, err := strconv.Atoi(data[0])
- if err != nil {
- return nil, fmt.Errorf("id: %w", err)
- }
-
- prevPrice, err := strconv.ParseFloat(data[3], 64)
- if err != nil {
- return nil, fmt.Errorf("prev_price: %w", err)
- }
-
- afterPrice, err := strconv.ParseFloat(data[4], 64)
- if err != nil {
- return nil, fmt.Errorf("after_price: %w", err)
- }
-
- return &SubsetRow{
- ID: id,
- Title: data[1],
- Body: data[2],
- PrevPrice: prevPrice,
- AfterPrice: afterPrice,
- }, nil
-}
diff --git a/cmd/eq/main.go b/cmd/eq/main.go
deleted file mode 100644
index ea63b16..0000000
--- a/cmd/eq/main.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "flag"
- "io"
- "log"
- "os"
-
- "github.com/expr-lang/expr"
-)
-
-var (
- minify = flag.Bool("minify", false, "minify JSON?")
- noColor = flag.Bool("no-color", false, "disable color output?")
-)
-
-func main() {
- flag.Parse()
-
- if _, ok := os.LookupEnv("NO_COLOR"); ok {
- *noColor = true
- }
-
- if flag.NArg() != 1 {
- log.Fatal("usage: eq <expression> < data.json")
- }
-
- program, err := expr.Compile(flag.Arg(0))
- if err != nil {
- log.Fatalf("can't compile program: %v", err)
- }
-
- dec := json.NewDecoder(os.Stdin)
- enc := json.NewEncoder(os.Stdout)
-
- if !*minify {
- enc.SetIndent("", " ")
- }
-
- for {
- obj := map[string]any{}
- if err := dec.Decode(&obj); err != nil {
- if err == io.EOF {
- break
- }
-
- log.Fatalf("can't decode JSON: %v", err)
- }
-
- output, err := expr.Run(program, obj)
- if err != nil {
- log.Fatalf("can't run program: %v", err)
- }
-
- if err := enc.Encode(output); err != nil {
- log.Fatalf("can't write JSON: %v", err)
- }
- }
-}
diff --git a/cmd/ff-primitive/main.go b/cmd/ff-primitive/main.go
deleted file mode 100644
index 3bd68c7..0000000
--- a/cmd/ff-primitive/main.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Command ff-primitive takes farbfeld data from standard in and applies http://primitive.lol to it.
-package main
-
-import (
- "flag"
- "image"
- "log"
- "os"
- "runtime"
- "runtime/pprof"
-
- "github.com/fogleman/primitive/primitive"
- farbfeld "github.com/hullerob/go.farbfeld"
- "within.website/x/internal"
-)
-
-var (
- shapeCount = flag.Int("count", 150, "number of shapes used")
- repeatShapeCount = flag.Int("repeat-count", 0, "number of extra shapes drawn in each step")
- alpha = flag.Int("alpha", 128, "alpha of all shapes")
- cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
-)
-
-func stepImg(img image.Image, count int) image.Image {
- bg := primitive.MakeColor(primitive.AverageImageColor(img))
- model := primitive.NewModel(img, bg, 512, runtime.NumCPU())
-
- for range make([]struct{}, count) {
- model.Step(primitive.ShapeTypeTriangle, *alpha, *repeatShapeCount)
- }
-
- return model.Context.Image()
-}
-
-func main() {
- internal.HandleStartup()
-
- if *cpuprofile != "" {
- f, err := os.Create(*cpuprofile)
- if err != nil {
- log.Fatal(err)
- }
- pprof.StartCPUProfile(f)
- defer pprof.StopCPUProfile()
- }
-
- img, err := farbfeld.Decode(os.Stdin)
- if err != nil {
- log.Fatal(err)
- }
-
- err = farbfeld.Encode(os.Stdout, stepImg(img, *shapeCount))
- if err != nil {
- log.Fatal(err)
- }
-}
diff --git a/cmd/relayd/main.go b/cmd/relayd/main.go
deleted file mode 100644
index fa66cd5..0000000
--- a/cmd/relayd/main.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Command relayd is a simple TLS terminator using let's encrypt.
-package main
-
-import (
- "context"
- "crypto/tls"
- "errors"
- "flag"
- "fmt"
- "log"
- "net/http"
- "net/http/httputil"
- "net/url"
- "time"
-
- "golang.org/x/crypto/acme/autocert"
- "within.website/x/internal"
-)
-
-func fwdhttps(w http.ResponseWriter, r *http.Request) {
- switch r.Method {
- case "POST", "PUT", "PATCH":
- http.Error(w, "HTTPS access required", 400)
- return
- default:
- http.RedirectHandler(fmt.Sprintf("https://%s%s", r.Host, r.RequestURI), http.StatusPermanentRedirect).ServeHTTP(w, r)
- }
-}
-
-var (
- insecurePort = flag.String("insecure-bind", ":80", "host/port to bind on for insecure (HTTP) traffic")
- securePort = flag.String("secure-bind", ":443", "host/port to bind on for secure (HTTPS) traffic")
- sitePort = flag.String("site-port", "3000", "port to http forward")
- siteDomain = flag.String("site-domain", "git.xeserv.us", "site port")
-)
-
-func main() {
- internal.HandleStartup()
-
- go http.ListenAndServe(*insecurePort, http.HandlerFunc(fwdhttps))
-
- m := autocert.Manager{
- Prompt: autocert.AcceptTOS,
- HostPolicy: autocert.HostWhitelist(*siteDomain),
- Cache: autocert.DirCache("./.relayd"),
- }
-
- u, err := url.Parse("http://127.0.0.1:" + *sitePort)
- if err != nil {
- panic(err)
- }
-
- go func() {
- err := http.ListenAndServe(*insecurePort, m.HTTPHandler(http.HandlerFunc(http.NotFound)))
- if err != nil {
- log.Fatal(err)
- }
- }()
-
- rp := httputil.NewSingleHostReverseProxy(u)
-
- s := &http.Server{
- IdleTimeout: 5 * time.Minute,
- Addr: *securePort,
- TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
- Handler: rp,
- }
- s.ListenAndServeTLS("", "")
-}
-
-func checkCert(ctx context.Context, host string) error {
- if host == *siteDomain {
- return nil
- }
-
- return errors.New("not allowed")
-}
diff --git a/cmd/robocadey2/fly.toml b/cmd/robocadey2/fly.toml
deleted file mode 100644
index 799ac1f..0000000
--- a/cmd/robocadey2/fly.toml
+++ /dev/null
@@ -1,26 +0,0 @@
-app = "xe-robocadey2"
-
-kill_signal = "SIGINT"
-kill_timeout = 5
-processes = []
-
-[deploy]
- strategy = "immediate"
-
-[build]
- image = "registry.fly.io/xe-robocadey2:latest"
-
-[env]
- STATE = "/data/robocadey2"
-
-[experimental]
- allowed_public_ports = []
- auto_rollback = true
-
-[mounts]
- source="robocadey2_state"
- destination="/data"
-
-[metrics]
-port = 8080
-path = "/.within/metrics"
diff --git a/cmd/robocadey2/main.go b/cmd/robocadey2/main.go
deleted file mode 100644
index 39b803b..0000000
--- a/cmd/robocadey2/main.go
+++ /dev/null
@@ -1,246 +0,0 @@
-package main
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "expvar"
- "flag"
- "fmt"
- "io"
- "log"
- "log/slog"
- "math/rand"
- "net/http"
- "os"
- "path/filepath"
- "strings"
- "time"
-
- "github.com/jaytaylor/html2text"
- "tailscale.com/metrics"
- "tailscale.com/tsnet"
- "tailscale.com/tsweb"
- "within.website/x/internal"
- "within.website/x/web/mastodon"
- "within.website/x/web/stablediffusion"
-)
-
-var (
- hostname = flag.String("hostname", "robocadey2", "hostname to use on tailnet")
- dataDir = flag.String("dir", dataLocation(), "stateful data directory")
- instance = flag.String("instance", "", "mastodon instance")
- token = flag.String("token", "", "oauth2 token")
-
- uploads = expvar.NewInt("gauge_robocadey2_uploads")
- retries = expvar.NewInt("gauge_robocadey2_retries")
-
- usageCount = metrics.LabelMap{Label: "user"}
-)
-
-func envOr(key, defaultVal string) string {
- if result, ok := os.LookupEnv(key); ok {
- return result
- }
- return defaultVal
-}
-
-func dataLocation() string {
- if dir, ok := os.LookupEnv("STATE"); ok {
- return dir
- }
- dir, err := os.UserConfigDir()
- if err != nil {
- return os.Getenv("STATE")
- }
- return filepath.Join(dir, "within.website", "x", "robocadey2")
-}
-
-func main() {
- internal.HandleStartup()
-
- os.MkdirAll(*dataDir, 0777)
-
- rand.Seed(time.Now().Unix())
-
- cli, err := mastodon.Authenticated("robocadey2", "https://within.website/.x.botinfo", *instance, *token)
- if err != nil {
- log.Fatal(err)
- }
-
- expvar.Publish("gauge_robocadey_usage_by_user", &usageCount)
- os.MkdirAll(filepath.Join(*dataDir, "tsnet"), 0777)
- srv := &tsnet.Server{
- Hostname: *hostname,
- Logf: log.New(io.Discard, "", 0).Printf,
- AuthKey: os.Getenv("TS_AUTHKEY"),
- Dir: filepath.Join(*dataDir, "tsnet"),
- }
-
- if err := srv.Start(); err != nil {
- log.Fatal(err)
- }
-
- httpCli := srv.HTTPClient()
- if err != nil {
- log.Fatal(err)
- }
-
- slog.Info("waiting for messages")
-
- b := &Bot{
- cli: cli,
- sd: &stablediffusion.Client{HTTP: httpCli},
- }
-
- go func() {
- lis, err := srv.Listen("tcp", ":80")
- if err != nil {
- log.Fatalf("tsnet can't listen: %v", err)
- }
-
- http.DefaultServeMux.HandleFunc("/debug/varz", tsweb.VarzHandler)
-
- defer srv.Close()
- defer lis.Close()
- log.Fatal(http.Serve(lis, http.DefaultServeMux))
- }()
-
- for {
- ctx, cancel := context.WithCancel(context.Background())
- ch, err := cli.StreamMessages(ctx, mastodon.WSSubscribeRequest{Type: "subscribe", Stream: "user"})
- if err != nil {
- log.Fatal(err)
- }
-
- for msg := range ch {
- switch msg.Event {
- case "notification":
- var n mastodon.Notification
- if err := json.Unmarshal([]byte(msg.Payload), &n); err != nil {
- slog.Error("can't parse notification", "err", err)
- continue
- }
-
- if n.Type != "mention" {
- continue
- }
-
- if err := b.handleNotification(n); err != nil {
- slog.Error("can't handle notification", "err", err, "content", n.Status.Content)
- continue
- }
- }
- }
- cancel()
- }
-}
-
-type Bot struct {
- cli *mastodon.Client
- sd *stablediffusion.Client
-}
-
-func (b *Bot) handleNotification(n mastodon.Notification) error {
- text, err := html2text.FromString(n.Status.Content, html2text.Options{OmitLinks: true})
- if err != nil {
- return nil
- }
- text = strings.ReplaceAll(text, "@ ", "")
-
- for _, m := range n.Status.Mentions {
- text = strings.ReplaceAll(text, m.Username, "")
- }
-
- text = strings.TrimSpace(text)
-
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
- defer cancel()
-
- seed := rand.Int()
-
- var extra string
-
- if rand.Intn(128) == 69 {
- extra = ", <lora:cdi:1>"
- }
-
- imgs, err := b.sd.Generate(ctx, stablediffusion.SimpleImageRequest{
- Prompt: "masterpiece, best quality, " + text + extra,
- NegativePrompt: "person in distance, worst quality, low quality, medium quality, deleted, lowres, comic, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry",
- Seed: seed,
- SamplerName: "DPM++ 2M Karras",
- BatchSize: 1,
- NIter: 1,
- Steps: 40,
- CfgScale: 7,
- Width: 512,
- Height: 512,
- SNoise: 1,
-
- OverrideSettingsRestoreAfterwards: true,
- })
- if err != nil {
- return err
- }
- usageCount.Add(n.Status.Account.Acct, 1)
-
- response := &strings.Builder{}
-
- response.WriteString("@")
- response.WriteString(n.Status.Account.Acct)
- response.WriteString(" ")
-
- for _, m := range n.Status.Mentions {
- if m.Acct == "robocadey" {
- continue
- }
-
- response.WriteString("@")
- response.WriteString(m.Acct)
- response.WriteString(" ")
- }
-
- var att *mastodon.Attachment
- tries := 4
-
- for tries != 0 {
- att, err = b.cli.UploadMedia(ctx, bytes.NewBuffer(imgs.Images[0]), "result.png", "prompt: "+text, "")
- if err != nil {
- slog.Error("retrying", "err", err, "tries", tries)
- time.Sleep(time.Second)
- tries--
- retries.Add(1)
- continue
- }
- uploads.Add(1)
- break
- }
-
- if tries == 0 {
- b.cli.CreateStatus(ctx, mastodon.CreateStatusParams{
- Status: response.String() + " @cadey please help: " + err.Error() + " (tried 4 times)",
- Visibility: n.Status.Visibility,
- InReplyTo: n.Status.ID,
- })
- }
-
- response.WriteString("here is your image:\n\n")
- fmt.Fprintf(response, "prompt: %s\n", text)
- fmt.Fprintf(response, "seed: %d\n", seed)
- fmt.Fprintln(response, "Generated with #xediffusion early alpha")
-
- if st, err := b.cli.CreateStatus(ctx, mastodon.CreateStatusParams{
- Status: response.String(),
- MediaIDs: []string{att.ID},
- SpoilerText: "AI generated image (can be NSFW)",
- Visibility: n.Status.Visibility,
- InReplyTo: n.Status.ID,
- }); err != nil {
- return err
- } else {
- slog.Info("status created", "url", st.URL, "responsible_party", n.Status.Account.Acct, "visibility", n.Status.Visibility)
- }
-
- return nil
-}
diff --git a/cmd/robocadey2/run.sh b/cmd/robocadey2/run.sh
deleted file mode 100644
index 91de2bb..0000000
--- a/cmd/robocadey2/run.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-while true; do
- go run .
- sleep 2
-done
diff --git a/cmd/robocadey2/yeetfile.js b/cmd/robocadey2/yeetfile.js
deleted file mode 100644
index 03c5849..0000000
--- a/cmd/robocadey2/yeetfile.js
+++ /dev/null
@@ -1,4 +0,0 @@
-nix.build(".#docker.robocadey2");
-docker.load();
-docker.push("registry.fly.io/xe-robocadey2:latest");
-fly.deploy();
diff --git a/cmd/xatci/main.go b/cmd/xatci/main.go
deleted file mode 100644
index ae01a93..0000000
--- a/cmd/xatci/main.go
+++ /dev/null
@@ -1,217 +0,0 @@
-package main
-
-import (
- "context"
- "flag"
- "fmt"
- "log"
- "log/slog"
- "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/x/internal"
- "within.website/x/web/marginalia"
- "within.website/x/web/openai/chatgpt"
- "within.website/x/web/openai/dalle"
-)
-
-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", "OpenAI model to use")
- telegramAdmin = flag.Int64("telegram-admin", 0, "Telegram bot admin")
- telegramToken = flag.String("telegram-token", "", "Telegram bot token")
-)
-
-func p[T any](t T) *T {
- return &t
-}
-
-func main() {
- internal.HandleStartup()
-
- mc := marginalia.New(*marginaliaToken, nil)
-
- cGPT := chatgpt.NewClient(*openAIToken)
- de := dalle.New(*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 {
- log.Fatal(err)
- }
-
- // Get updates channel
- updates, err := bot.UpdatesViaLongPolling(nil)
- if err != nil {
- log.Fatal(err)
- }
-
- // Create bot handler and specify from where to get updates
- bh, err := th.NewBotHandler(bot, updates)
- if err != nil {
- log.Fatal(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 {
- slog.Error("can't send message", "err", 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()
-
- q := strings.Join(strings.Split(update.Message.Text, " ")[1:], " ")
-
- lg := slog.Default().With(
- "telegram_requestor", update.Message.From.ID,
- "telegram_requestor_name", fmt.Sprintf("%s %s", update.Message.From.FirstName, update.Message.From.LastName),
- "image_prompt", q,
- )
-
- resp, err := de.GenerateImage(ctx, dalle.Options{
- Model: dalle.DALLE3,
- Prompt: q,
- Size: p(dalle.SizeHDWide),
- })
- if err != nil {
- lg.Error("can't generate image", "err", err)
- bot.SendMessage(tu.Message(
- tu.ID(update.Message.Chat.ID),
- fmt.Sprintf("Error: %v", err),
- ))
- return
- }
-
- lg.Debug("got response", "resp", resp)
-
- photo := tu.Photo(
- tu.ID(update.Message.Chat.ID),
- tu.FileFromURL(resp.Data[0].URL),
- ).WithCaption(q)
-
- if _, err := bot.SendPhoto(photo); err != nil {
- lg.Error("can't send photo", "err", err)
- return
- }
- }, th.CommandEqual("image"))
-
- 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()
-
- q := strings.Join(strings.Split(update.Message.Text, " ")[1:], " ")
-
- lg := slog.Default().With(
- "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 {
- lg.Error("can't search", "err", 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)
-
- lg.Info("resolving article", "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 {
- lg.Error("can't summarize article", "err", 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 {
- lg.Error("can't send final message", "err", err)
- return
- }
-
- lg.Info("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())
-
- slog.Info("started")
-
- // Start handling updates
- bh.Start()
-}