Blame
Date:
Sun Jul 3 08:36:57 2022 UTC
Message:
chmod downloaded files as 0644

while here also switch ioutil.TempFile to os.CreateTemp (which is now
the same)
001
2021-04-27
op
package main
002
2021-04-27
op
003
2021-04-27
op
import (
004
2021-04-27
op
"crypto/tls"
005
2021-04-27
op
"flag"
006
2021-04-27
op
"fmt"
007
2021-04-27
op
"io"
008
2021-04-27
op
"log"
009
2021-04-27
op
"net/http"
010
2022-07-03
op
"os"
011
2021-07-30
op
"path"
012
2021-04-27
op
"path/filepath"
013
2021-04-27
op
"regexp"
014
2021-11-07
op
"strings"
015
2021-04-27
op
016
2022-01-08
op
"github.com/andybalholm/cascadia"
017
2021-04-27
op
irc "github.com/fluffle/goirc/client"
018
2021-12-02
op
"golang.org/x/net/html"
019
2021-04-27
op
)
020
2021-04-27
op
021
2021-04-27
op
var (
022
2021-11-07
op
baseurl = flag.String("baseurl", "gemini://m2i.omarpolo.com", "base url")
023
2021-04-27
op
matrixOutDir = flag.String("matrix-out", "", "matrix out directory")
024
2021-04-27
op
025
2021-11-07
op
msgRe = regexp.MustCompile(`https://.*/[^\s]+\.(txt|png|jpg|jpeg|gif)`)
026
2021-07-30
op
channel = "#gemini-it"
027
2021-11-07
op
028
2021-11-07
op
tooLongRe = regexp.MustCompile(`full message at (https://libera.ems.host/.*)[)]`)
029
2021-12-02
op
030
2021-12-02
op
httplink = regexp.MustCompile(`https?://[^\s)]+`)
031
2022-01-08
op
gemlink = regexp.MustCompile(`gemini://[^\s)]+`)
032
2021-04-27
op
)
033
2021-04-27
op
034
2021-04-27
op
func matrix2gemini(conn *irc.Conn, line *irc.Line) {
035
2021-07-30
op
matches := msgRe.FindAllString(line.Text(), -1)
036
2021-04-27
op
037
2021-04-27
op
// it's not a good idea to defer inside a loop, but we know
038
2021-04-27
op
// len(matches) is small (usually just 1). Morover, I like
039
2021-04-27
op
// living in danger!
040
2021-04-27
op
041
2021-04-27
op
for _, link := range matches {
042
2021-04-27
op
resp, err := http.Get(link)
043
2021-04-27
op
if err != nil {
044
2021-04-27
op
conn.Privmsg(
045
2021-04-27
op
channel,
046
2021-04-27
op
fmt.Sprintf("failed to download %q: %s", link, err),
047
2021-04-27
op
)
048
2021-04-27
op
continue
049
2021-04-27
op
}
050
2021-04-27
op
defer resp.Body.Close()
051
2021-04-27
op
052
2021-07-30
op
ext := path.Ext(link)
053
2022-07-03
op
tmpfile, err := os.CreateTemp(*matrixOutDir, "message-*"+ext)
054
2021-04-27
op
if err != nil {
055
2021-04-27
op
conn.Privmsg(channel, fmt.Sprintf("failed to tmpfile: %s", err))
056
2021-04-27
op
return
057
2021-04-27
op
}
058
2021-04-27
op
defer tmpfile.Close()
059
2021-04-27
op
060
2022-07-03
op
os.Chmod(tmpfile.Name(), 0644)
061
2022-07-03
op
062
2021-04-27
op
io.Copy(tmpfile, resp.Body)
063
2021-04-27
op
064
2021-04-27
op
conn.Privmsg(
065
2021-04-27
op
channel,
066
2021-04-27
op
fmt.Sprintf(
067
2021-04-27
op
"better: %s/%s",
068
2021-04-27
op
*baseurl,
069
2021-04-27
op
filepath.Base(tmpfile.Name()),
070
2021-04-27
op
),
071
2021-04-27
op
)
072
2021-04-27
op
}
073
2021-04-27
op
}
074
2021-04-27
op
075
2021-11-07
op
func messageTooLong(conn *irc.Conn, line *irc.Line) {
076
2021-11-07
op
matches := tooLongRe.FindStringSubmatch(line.Text())
077
2021-11-07
op
if len(matches) != 2 {
078
2021-11-07
op
return
079
2021-11-07
op
}
080
2021-11-07
op
081
2021-11-07
op
url := matches[1]
082
2021-11-07
op
083
2021-11-07
op
resp, err := http.Get(url)
084
2021-11-07
op
if err != nil {
085
2021-11-07
op
conn.Privmsg(
086
2021-11-07
op
channel,
087
2021-11-07
op
fmt.Sprintf("failed to download %q: %s", url, err),
088
2021-11-07
op
)
089
2021-11-07
op
return
090
2021-11-07
op
}
091
2021-11-07
op
defer resp.Body.Close()
092
2021-11-07
op
093
2021-11-07
op
sb := &strings.Builder{}
094
2021-11-07
op
if _, err := io.Copy(sb, resp.Body); err != nil {
095
2021-11-07
op
conn.Privmsg(
096
2021-11-07
op
channel,
097
2021-11-07
op
fmt.Sprintf("failed to read body of %q: %s", url, err),
098
2021-11-07
op
)
099
2021-11-07
op
return
100
2021-11-07
op
}
101
2021-11-07
op
102
2021-11-07
op
conn.Privmsg(channel, fmt.Sprintf("%s ha detto:", line.Nick))
103
2021-11-07
op
for _, line := range strings.Split(sb.String(), "\n") {
104
2021-11-07
op
conn.Privmsg(
105
2021-11-07
op
channel,
106
2021-11-07
op
line,
107
2021-11-07
op
)
108
2021-11-07
op
}
109
2021-11-07
op
}
110
2021-11-07
op
111
2021-12-02
op
func stringifyNode(node *html.Node) string {
112
2021-12-02
op
s := ""
113
2021-12-02
op
114
2021-12-02
op
if node.Type == html.TextNode {
115
2021-12-02
op
return node.Data
116
2021-12-02
op
}
117
2021-12-02
op
118
2021-12-02
op
for child := node.FirstChild; child != nil; child = child.NextSibling {
119
2021-12-02
op
s += stringifyNode(child)
120
2021-12-02
op
}
121
2021-12-02
op
122
2021-12-02
op
return s
123
2021-12-02
op
}
124
2021-12-02
op
125
2022-01-08
op
func wwwpagetitle(conn *irc.Conn, line *irc.Line) {
126
2021-12-02
op
matches := httplink.FindAllString(line.Text(), -1)
127
2021-12-02
op
128
2021-12-02
op
for _, link := range matches {
129
2021-12-02
op
log.Println("fetching", link, "...")
130
2021-12-02
op
131
2021-12-02
op
resp, err := http.Get(link)
132
2021-12-02
op
if err != nil {
133
2021-12-02
op
continue
134
2021-12-02
op
}
135
2021-12-02
op
defer resp.Body.Close()
136
2021-12-02
op
137
2021-12-02
op
doc, err := html.Parse(resp.Body)
138
2021-12-02
op
if err != nil {
139
2021-12-02
op
continue
140
2021-12-02
op
}
141
2021-12-02
op
142
2022-01-08
op
sel := cascadia.MustCompile("head > title")
143
2022-01-08
op
n := cascadia.Query(doc, sel)
144
2022-01-08
op
145
2022-01-08
op
if n == nil {
146
2021-12-02
op
continue
147
2021-12-02
op
}
148
2022-01-08
op
149
2022-01-08
op
title := stringifyNode(n)
150
2022-01-08
op
if len(title) > 50 {
151
2022-01-08
op
title = title[:50]
152
2022-01-08
op
}
153
2022-01-08
op
conn.Privmsg(channel, stringifyNode(n))
154
2021-12-02
op
}
155
2021-12-02
op
}
156
2021-12-02
op
157
2022-01-08
op
func gempagetitle(conn *irc.Conn, line *irc.Line) {
158
2022-01-08
op
matches := gemlink.FindAllString(line.Text(), -1)
159
2022-01-08
op
160
2022-01-08
op
for _, link := range matches {
161
2022-01-08
op
log.Println("fetching", link, "...")
162
2022-01-08
op
title, err := geminiTitle(link)
163
2022-01-08
op
if err != nil {
164
2022-01-08
op
continue
165
2022-01-08
op
}
166
2022-01-08
op
167
2022-01-08
op
conn.Privmsg(channel, title)
168
2022-01-08
op
}
169
2022-01-08
op
}
170
2022-01-08
op
171
2022-06-29
op
func pong(conn *irc.Conn, line *irc.Line) {
172
2022-06-29
op
if line.Text() != ",ping" {
173
2022-06-29
op
return
174
2022-06-29
op
}
175
2022-06-29
op
conn.Privmsg(
176
2022-06-29
op
channel,
177
2022-06-29
op
"pong :)",
178
2022-06-29
op
)
179
2022-06-29
op
}
180
2022-06-29
op
181
2021-04-27
op
func dostuff(conn *irc.Conn, line *irc.Line) {
182
2021-04-27
op
matrix2gemini(conn, line)
183
2021-11-07
op
messageTooLong(conn, line)
184
2022-01-08
op
wwwpagetitle(conn, line)
185
2022-01-08
op
gempagetitle(conn, line)
186
2022-06-29
op
pong(conn, line)
187
2021-04-27
op
// ...
188
2021-04-27
op
}
189
2021-04-27
op
190
2021-04-27
op
func main() {
191
2021-04-27
op
flag.Parse()
192
2021-04-27
op
193
2021-04-27
op
cfg := irc.NewConfig("gemitbot")
194
2021-04-27
op
cfg.SSL = true
195
2021-07-30
op
cfg.SSLConfig = &tls.Config{ServerName: "irc.libera.chat"}
196
2021-07-30
op
cfg.Server = "irc.libera.chat:7000"
197
2021-04-27
op
cfg.NewNick = func(n string) string { return n + "^" }
198
2021-04-27
op
199
2021-04-27
op
c := irc.Client(cfg)
200
2021-04-27
op
201
2021-04-27
op
c.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) {
202
2021-04-27
op
log.Println("connected, joining", channel)
203
2021-04-27
op
conn.Join(channel)
204
2021-04-27
op
})
205
2021-04-27
op
206
2021-04-27
op
c.HandleFunc(irc.PRIVMSG, dostuff)
207
2021-04-27
op
c.HandleFunc(irc.ACTION, dostuff)
208
2021-04-27
op
209
2021-04-27
op
quit := make(chan bool)
210
2021-04-27
op
211
2021-04-27
op
c.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) {
212
2021-04-27
op
quit <- true
213
2021-04-27
op
})
214
2021-04-27
op
215
2021-04-27
op
if err := c.Connect(); err != nil {
216
2021-04-27
op
log.Fatalln("connection error:", err)
217
2021-04-27
op
}
218
2021-04-27
op
219
2021-04-27
op
<-quit
220
2021-04-27
op
}
Omar Polo