forked from tildetown/town
Compare commits
2 Commits
544a1f6ebd
...
9bc66c4516
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bc66c4516 | ||
|
|
40951a6846 |
77
external/cmd/signup/main.go
vendored
77
external/cmd/signup/main.go
vendored
@ -3,14 +3,18 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.tilde.town/tildetown/town/external/lockingwriter"
|
||||||
"git.tilde.town/tildetown/town/models"
|
"git.tilde.town/tildetown/town/models"
|
||||||
"git.tilde.town/tildetown/town/signup"
|
"git.tilde.town/tildetown/town/signup"
|
||||||
"github.com/MakeNowJust/heredoc/v2"
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
@ -21,7 +25,6 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
maxInputLength = 10000
|
maxInputLength = 10000
|
||||||
logDir = "/town/var/signups/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type scene struct {
|
type scene struct {
|
||||||
@ -110,15 +113,42 @@ func (c *character) Say(msg string) string {
|
|||||||
strings.TrimSpace(msg))
|
strings.TrimSpace(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
var ErrNoSuchDomain = errors.New("no host found for email address")
|
||||||
logFile := path.Join(logDir, fmt.Sprintf("%d", time.Now().Unix()))
|
var ErrNoSuchMailserver = errors.New("no mail server found for email address")
|
||||||
logF, err := os.Create(logFile)
|
|
||||||
if err != nil {
|
// DigMX does some grubbing around to attempt to find valid email hosts, and
|
||||||
fmt.Fprintln(os.Stderr, err)
|
// then runs then through [net.LookupMX] and returns their mailserver domains.
|
||||||
os.Exit(1)
|
// may return [ErrNoSuchDomain] or [ErrNoSuchMailserver].
|
||||||
|
func DigMX(raw string) (domains []string, err error) {
|
||||||
|
re := regexp.MustCompile(`@[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+\b`) // good enough
|
||||||
|
candidates := re.FindAllString(raw, -1)
|
||||||
|
|
||||||
|
// the error checking tries to be very generous: if anything comes up
|
||||||
|
// positive we will throw no errors and just assume the rest was a fluke.
|
||||||
|
ok := false
|
||||||
|
for _, host := range candidates {
|
||||||
|
records, e := net.LookupMX(host[1:])
|
||||||
|
if e != nil {
|
||||||
|
err = ErrNoSuchDomain
|
||||||
|
} else if len(records) == 0 {
|
||||||
|
err = ErrNoSuchMailserver
|
||||||
|
} else {
|
||||||
|
ok = true
|
||||||
|
for _, record := range records {
|
||||||
|
domains = append(domains, record.Host)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger := log.New(logF, "", log.Ldate|log.Ltime)
|
if ok {
|
||||||
|
return domains, nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
lw := lockingwriter.New()
|
||||||
|
logger := log.New(lw, "signup: ", log.Ldate|log.Ltime|log.LUTC|log.Lshortfile|log.Lmsgprefix)
|
||||||
|
|
||||||
db, err := signup.ConnectDB()
|
db, err := signup.ConnectDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -173,6 +203,10 @@ func _main(l *log.Logger, db *sql.DB) error {
|
|||||||
su.Created = time.Now()
|
su.Created = time.Now()
|
||||||
err := su.Insert(db)
|
err := su.Insert(db)
|
||||||
|
|
||||||
|
for _, note := range su.Notes {
|
||||||
|
err = note.Insert(db)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Printf("failed to write to db: %s", err.Error())
|
l.Printf("failed to write to db: %s", err.Error())
|
||||||
l.Printf("dumping values: %#v", su)
|
l.Printf("dumping values: %#v", su)
|
||||||
@ -201,9 +235,32 @@ func _main(l *log.Logger, db *sql.DB) error {
|
|||||||
`),
|
`),
|
||||||
"i'm sorry, before going further could you share an email with me?",
|
"i'm sorry, before going further could you share an email with me?",
|
||||||
newCharacter("wire guy", "a lil homonculus made of discarded computer cables"),
|
newCharacter("wire guy", "a lil homonculus made of discarded computer cables"),
|
||||||
func(s *scene) { su.Email = string(s.Input.Bytes()) },
|
func(s *scene) {
|
||||||
|
su.Email = string(s.Input.Bytes())
|
||||||
|
suspiciousHosts, err := models.SuspiciousHosts(db)
|
||||||
|
if err != nil {
|
||||||
|
l.Println("could not connect to suspicious hosts db")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var shDomains []string
|
||||||
|
for _, host := range suspiciousHosts {
|
||||||
|
shDomains = append(shDomains, host.Domain)
|
||||||
|
}
|
||||||
|
if records, err := DigMX(su.Email); err == nil {
|
||||||
|
for _, record := range records {
|
||||||
|
if slices.Contains(shDomains, record) {
|
||||||
|
su.Notes = append(su.Notes, models.SignupNote{
|
||||||
|
Author: "dns",
|
||||||
|
Content: fmt.Sprintf("email address has suspicious host %s", record),
|
||||||
|
SignupID: su.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
func(s *scene, tv *tview.TextView, msg string) {
|
func(s *scene, tv *tview.TextView, msg string) {
|
||||||
// TODO could check and see if it's email shaped and admonish if not
|
// TODO could check and see if it's email shaped and admonish if not
|
||||||
|
// NOTE(nbsp): DigMX call can see if email is invalid but this isn't used yet
|
||||||
trimmed := strings.TrimSpace(msg)
|
trimmed := strings.TrimSpace(msg)
|
||||||
fmt.Fprintln(tv, s.Host.Say(fmt.Sprintf("I heard '%s'. Is that right? if so, /nod", trimmed)))
|
fmt.Fprintln(tv, s.Host.Say(fmt.Sprintf("I heard '%s'. Is that right? if so, /nod", trimmed)))
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -193,3 +193,35 @@ func (s *TownSignup) All(db *sql.DB) ([]*TownSignup, error) {
|
|||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SuspiciousHost struct {
|
||||||
|
ID int64
|
||||||
|
Domain string
|
||||||
|
CommonName string
|
||||||
|
Tier int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func SuspiciousHosts(db *sql.DB) ([]SuspiciousHost, error) {
|
||||||
|
rows, err := db.Query(`SELECT id, domain, common_name, tier FROM suspicious_hosts`)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
out := []SuspiciousHost{}
|
||||||
|
for rows.Next() {
|
||||||
|
sh := SuspiciousHost{}
|
||||||
|
if err = rows.Scan(
|
||||||
|
&sh.ID,
|
||||||
|
&sh.Domain,
|
||||||
|
&sh.CommonName,
|
||||||
|
&sh.Tier,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out = append(out, sh)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -24,3 +24,9 @@ CREATE TABLE IF NOT EXISTS notes (
|
|||||||
|
|
||||||
FOREIGN KEY (signupid) REFERENCES signups(signupid)
|
FOREIGN KEY (signupid) REFERENCES signups(signupid)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- 2025-11-22: bad hosts
|
||||||
|
CREATE TABLE IF NOT EXISTS suspicious_hosts (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
domain TEXT
|
||||||
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user