Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v14 #51

Merged
merged 7 commits into from
Mar 2, 2024
Merged

v14 #51

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022 kakakaya
Copyright (c) 2022 kakakaya, Ryota Kayanuma

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
19 changes: 0 additions & 19 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"log/slog"
"net/http"
"os"
"os/exec"
goruntime "runtime"
"strings"
"time"

Expand Down Expand Up @@ -166,23 +164,6 @@ func (a *App) OpenLogDirectory() error {
return openDirectory(f)
}

func OpenURL(url string) error {
var cmd string
var args []string

switch goruntime.GOOS {
case "windows":
cmd = "cmd"
args = []string{"/c", "start"}
case "darwin":
cmd = "open"
default:
cmd = "xdg-open"
}
args = append(args, url)
return exec.Command(cmd, args...).Start()
}

func (a *App) SetXRPCClient() error {

// Build xrpc.Client
Expand Down
134 changes: 130 additions & 4 deletions bluesky.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,151 @@
package main

import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"strings"
"time"

"github.com/PuerkitoBio/goquery"
comatproto "github.com/bluesky-social/indigo/api/atproto"
"github.com/bluesky-social/indigo/api/bsky"
appbsky "github.com/bluesky-social/indigo/api/bsky"
lexutil "github.com/bluesky-social/indigo/lex/util"
"github.com/bluesky-social/indigo/xrpc"
)

func addLink(xrpcc *xrpc.Client, post *bsky.FeedPost, link string) {
doc, err := goquery.NewDocument(link)
var title string
var description string
var imgURL string

if err == nil {
title = doc.Find(`title`).Text()
description, _ = doc.Find(`meta[property="description"]`).Attr("content")
imgURL, _ = doc.Find(`meta[property="og:image"]`).Attr("content")
if title == "" {
title, _ = doc.Find(`meta[property="og:title"]`).Attr("content")
if title == "" {
title = link
}
}
if description == "" {
description, _ = doc.Find(`meta[property="og:description"]`).Attr("content")
if description == "" {
description = link
}
}
post.Embed.EmbedExternal = &bsky.EmbedExternal{
External: &bsky.EmbedExternal_External{
Description: description,
Title: title,
Uri: link,
},
}
} else {
post.Embed.EmbedExternal = &bsky.EmbedExternal{
External: &bsky.EmbedExternal_External{
Uri: link,
},
}
}
if imgURL != "" && post.Embed.EmbedExternal != nil {
resp, err := http.Get(imgURL)
if err == nil && resp.StatusCode == http.StatusOK {
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err == nil {
resp, err := comatproto.RepoUploadBlob(context.TODO(), xrpcc, bytes.NewReader(b))
if err == nil {
post.Embed.EmbedExternal.External.Thumb = &lexutil.LexBlob{
Ref: resp.Blob.Ref,
MimeType: http.DetectContentType(b),
Size: resp.Blob.Size,
}
}
}
}
}
}

func BskyFeedPost(xrpcc *xrpc.Client, text string) (string, error) {
// Post given text to Bluesky, with app.bsky.feed.post.
if text == "" || strings.TrimSpace(text) == "" {
return "", fmt.Errorf("no text specified")
}

post := &appbsky.FeedPost{
Text: text,
CreatedAt: time.Time.UTC(time.Now()).Format("2006-01-02T15:04:05.000Z"),
}

for _, entry := range extractLinksBytes(text) {
post.Facets = append(post.Facets, &appbsky.RichtextFacet{
Features: []*appbsky.RichtextFacet_Features_Elem{
{
RichtextFacet_Link: &appbsky.RichtextFacet_Link{
Uri: entry.text,
},
},
},
Index: &appbsky.RichtextFacet_ByteSlice{
ByteStart: entry.start,
ByteEnd: entry.end,
},
})
if post.Embed == nil {
post.Embed = &appbsky.FeedPost_Embed{}
}
if post.Embed.EmbedExternal == nil {
addLink(xrpcc, post, entry.text)
}
}

for _, entry := range extractMentionsBytes(text) {
profile, err := appbsky.ActorGetProfile(context.TODO(), xrpcc, entry.text)
if err != nil {
return "", err
}
post.Facets = append(post.Facets, &appbsky.RichtextFacet{
Features: []*appbsky.RichtextFacet_Features_Elem{
{
RichtextFacet_Mention: &appbsky.RichtextFacet_Mention{
Did: profile.Did,
},
},
},
Index: &appbsky.RichtextFacet_ByteSlice{
ByteStart: entry.start,
ByteEnd: entry.end,
},
})
}

for _, entry := range extractTagsBytes(text) {
post.Facets = append(post.Facets, &appbsky.RichtextFacet{
Features: []*appbsky.RichtextFacet_Features_Elem{
{
RichtextFacet_Tag: &appbsky.RichtextFacet_Tag{
Tag: entry.text,
},
},
},
Index: &appbsky.RichtextFacet_ByteSlice{
ByteStart: entry.start,
ByteEnd: entry.end,
},
})
}

resp, err := comatproto.RepoCreateRecord(context.TODO(), xrpcc, &comatproto.RepoCreateRecord_Input{
Collection: "app.bsky.feed.post",
Repo: xrpcc.Auth.Did,
Record: &lexutil.LexiconTypeDecoder{
Val: &appbsky.FeedPost{
Text: text,
CreatedAt: time.Now().Format("2006-01-02T15:04:05.000Z"),
},
Val: post,
},
})
if err != nil {
Expand Down
16 changes: 8 additions & 8 deletions continent.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@ func (a *App) DispatchCommand(text string) string {
case "/help":
{
if len(words) < 2 {
OpenURL("https://github.com/kakakaya/mazesoba-continent/blob/main/README.md")
runtime.BrowserOpenURL(a.ctx, "https://github.com/kakakaya/mazesoba-continent/blob/main/README.md")
}
switch words[1] {
case "config":
{
OpenURL("https://github.com/kakakaya/mazesoba-continent/tree/main/docs/CONFIG.md")
runtime.BrowserOpenURL(a.ctx, "https://github.com/kakakaya/mazesoba-continent/tree/main/docs/CONFIG.md")
}
case "command":
{
OpenURL("https://github.com/kakakaya/mazesoba-continent/tree/main/docs/SLASH_COMMAND.md")
runtime.BrowserOpenURL(a.ctx, "https://github.com/kakakaya/mazesoba-continent/tree/main/docs/SLASH_COMMAND.md")
}
default:
{
OpenURL("https://github.com/kakakaya/mazesoba-continent/blob/main/README.md")
runtime.BrowserOpenURL(a.ctx, "https://github.com/kakakaya/mazesoba-continent/blob/main/README.md")
}
}
return ""
Expand All @@ -54,7 +54,7 @@ func (a *App) DispatchCommand(text string) string {
case "profile":
{
handle_or_did := words[2]
OpenURL(fmt.Sprintf("https://bsky.app/profile/%s", handle_or_did))
runtime.BrowserOpenURL(a.ctx, fmt.Sprintf("https://bsky.app/profile/%s", handle_or_did))
}
case "search", "s":
{
Expand All @@ -71,11 +71,11 @@ func (a *App) DispatchCommand(text string) string {
q.Add("q", strings.Join(words[2:], " "))
req.URL.RawQuery = q.Encode()

OpenURL(req.URL.String())
runtime.BrowserOpenURL(a.ctx, req.URL.String())
}
default:
{
OpenURL(words[1]) // NOTE: TBC
runtime.BrowserOpenURL(a.ctx, words[1]) // NOTE: TBC
}
}
return ""
Expand Down Expand Up @@ -112,7 +112,7 @@ func (a *App) DispatchCommand(text string) string {
switch words[1] {
case "egosearch", "egs":
{
OpenURL("https://bsky.app/search?q=%E3%81%BE%E3%81%9C%E3%81%9D%E3%81%B0%E5%A4%A7%E9%99%B8")
runtime.BrowserOpenURL(a.ctx, "https://bsky.app/search?q=%E3%81%BE%E3%81%9C%E3%81%9D%E3%81%B0%E5%A4%A7%E9%99%B8")
}
}
return ""
Expand Down
103 changes: 103 additions & 0 deletions extract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// This file is copied from: https://github.com/mattn/bsky/blob/05cbf0a2797313b779950ee4afaa9adcf92c58f3/extract.go
package main

import (
"regexp"
"strings"
)

const (
urlPattern = `https?://[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+`
mentionPattern = `@[a-zA-Z0-9.]+`
tagPattern = `\B#\S+`
)

var (
urlRe = regexp.MustCompile(urlPattern)
mentionRe = regexp.MustCompile(mentionPattern)
tagRe = regexp.MustCompile(tagPattern)
)

type entry struct {
start int64
end int64
text string
}

func extractLinks(text string) []entry {
var result []entry
matches := urlRe.FindAllStringSubmatchIndex(text, -1)
for _, m := range matches {
result = append(result, entry{
text: text[m[0]:m[1]],
start: int64(len([]rune(text[0:m[0]]))),
end: int64(len([]rune(text[0:m[1]])))},
)
}
return result
}

func extractLinksBytes(text string) []entry {
var result []entry
matches := urlRe.FindAllStringSubmatchIndex(text, -1)
for _, m := range matches {
result = append(result, entry{
text: text[m[0]:m[1]],
start: int64(len(text[0:m[0]])),
end: int64(len(text[0:m[1]]))},
)
}
return result
}

func extractMentions(text string) []entry {
var result []entry
matches := mentionRe.FindAllStringSubmatchIndex(text, -1)
for _, m := range matches {
result = append(result, entry{
text: strings.TrimPrefix(text[m[0]:m[1]], "@"),
start: int64(len([]rune(text[0:m[0]]))),
end: int64(len([]rune(text[0:m[1]])))},
)
}
return result
}

func extractMentionsBytes(text string) []entry {
var result []entry
matches := mentionRe.FindAllStringSubmatchIndex(text, -1)
for _, m := range matches {
result = append(result, entry{
text: strings.TrimPrefix(text[m[0]:m[1]], "@"),
start: int64(len(text[0:m[0]])),
end: int64(len(text[0:m[1]]))},
)
}
return result
}

func extractTags(text string) []entry {
var result []entry
matches := tagRe.FindAllStringSubmatchIndex(text, -1)
for _, m := range matches {
result = append(result, entry{
text: strings.TrimPrefix(text[m[0]:m[1]], "#"),
start: int64(len([]rune(text[0:m[0]]))),
end: int64(len([]rune(text[0:m[1]])))},
)
}
return result
}

func extractTagsBytes(text string) []entry {
var result []entry
matches := tagRe.FindAllStringSubmatchIndex(text, -1)
for _, m := range matches {
result = append(result, entry{
text: strings.TrimPrefix(text[m[0]:m[1]], "#"),
start: int64(len(text[0:m[0]])),
end: int64(len(text[0:m[1]]))},
)
}
return result
}
2 changes: 1 addition & 1 deletion frontend/package.json.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8bc973e96983b95b62df8eb19fc1e169
6faf32c9fcd1f3bdc344cce03c10821a
Loading
Loading