openidec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

main.go (4479B)


      1 package main
      2 
      3 import (
      4 	"bufio"
      5 	"flag"
      6 	"fmt"
      7 	"io"
      8 	"io/ioutil"
      9 	"os"
     10 	"regexp"
     11 	"sort"
     12 	"strings"
     13 	"time"
     14 
     15 	"git.openbsd.org.ru/vasyahacker/openidec/ii"
     16 )
     17 
     18 func open_db(path string) *ii.DB {
     19 	db := ii.OpenDB(path)
     20 	if db == nil {
     21 		fmt.Printf("Can no open db: %s\n", path)
     22 		os.Exit(1)
     23 	}
     24 	return db
     25 }
     26 
     27 func GetFile(path string) string {
     28 	var file *os.File
     29 	var err error
     30 	if path == "-" {
     31 		file = os.Stdin
     32 	} else {
     33 		file, err = os.Open(path)
     34 		if err != nil {
     35 			fmt.Printf("Can not open file %s: %s\n", path, err)
     36 			os.Exit(1)
     37 		}
     38 		defer file.Close()
     39 	}
     40 	b, err := ioutil.ReadAll(file)
     41 	if err != nil {
     42 		fmt.Printf("Can not read file %s: %s\n", path, err)
     43 		os.Exit(1)
     44 	}
     45 	return string(b)
     46 }
     47 
     48 var urlRegex = regexp.MustCompile(`(http|ftp|https|gemini)://[^ <>"]+`)
     49 
     50 func gemini(f io.Writer, m *ii.Msg) {
     51 	fmt.Fprintln(f, "# "+m.Subj)
     52 	if m.To != "All" && m.To != m.From {
     53 		fmt.Fprintf(f, "To: %s\n\n", m.To)
     54 	}
     55 	d := time.Unix(m.Date, 0).Format("2006-01-02 15:04:05")
     56 	fmt.Fprintf(f, "by %s on %s\n\n", m.From, d)
     57 	temp := strings.Split(m.Text, "\n")
     58 	pre := false
     59 	xpm := false
     60 	link := 0
     61 	var links []string
     62 	for _, l := range temp {
     63 		l = strings.Replace(l, "\r", "", -1)
     64 		if pre {
     65 			if l == "====" {
     66 				l = "```"
     67 				pre = false
     68 			}
     69 		} else if xpm {
     70 			if strings.HasSuffix(l, "};") {
     71 				xpm = false
     72 				fmt.Fprintln(f, l)
     73 				fmt.Fprintln(f, "```")
     74 				continue
     75 			}
     76 		} else {
     77 			if l == "====" {
     78 				l = "```"
     79 				pre = true
     80 			} else if strings.HasPrefix(l, "/* XPM */") {
     81 				fmt.Fprintln(f, "```")
     82 				xpm = true
     83 			}
     84 		}
     85 		if !pre && !xpm {
     86 			l = string(urlRegex.ReplaceAllFunc([]byte(l),
     87 				func(line []byte) []byte {
     88 					link++
     89 					s := string(line)
     90 					links = append(links, fmt.Sprintf("=> %s %s [%d]",
     91 						s, s, link))
     92 					return []byte(fmt.Sprintf("%s [%d]", s, link))
     93 				}))
     94 		}
     95 		fmt.Fprintln(f, l)
     96 	}
     97 	for _, v := range links {
     98 		fmt.Fprintln(f, v)
     99 	}
    100 }
    101 
    102 func str_esc(l string) string {
    103 	l = strings.Replace(l, "&", "&amp;", -1)
    104 	l = strings.Replace(l, "<", "&lt;", -1)
    105 	l = strings.Replace(l, ">", "&gt;", -1)
    106 	return l
    107 }
    108 
    109 func main() {
    110 	ii.OpenLog(ioutil.Discard, os.Stdout, os.Stderr)
    111 
    112 	db_opt := flag.String("db", "./db", "II database path (directory)")
    113 	data_opt := flag.String("data", "./data", "Output path (directory)")
    114 	url_opt := flag.String("url", "localhost", "Url of station")
    115 	verbose_opt := flag.Bool("v", false, "Verbose")
    116 	title_opt := flag.String("title", "ii/idec networks", "Title")
    117 	author_opt := flag.String("author", "anonymous", "Author")
    118 	flag.Parse()
    119 	if *verbose_opt {
    120 		ii.OpenLog(os.Stdout, os.Stdout, os.Stderr)
    121 	}
    122 
    123 	args := flag.Args()
    124 	if len(args) < 1 {
    125 		fmt.Printf(`Help: %s [options] command [arguments]
    126 Commands:
    127 	-data <path> gemini - generate gemini data
    128 Options:
    129         -db=<path>                    - database path
    130 `, os.Args[0])
    131 		os.Exit(1)
    132 	}
    133 	switch cmd := args[0]; cmd {
    134 	case "gemini":
    135 		db := open_db(*db_opt)
    136 		db.Lock()
    137 		defer db.Unlock()
    138 		if err := db.LoadIndex(); err != nil {
    139 			return
    140 		}
    141 
    142 		scanner := bufio.NewScanner(os.Stdin)
    143 		var mis []*ii.Msg
    144 		for scanner.Scan() {
    145 			mi := db.LookupFast(scanner.Text(), false)
    146 			if mi != nil {
    147 				mis = append(mis, db.Get(mi.Id))
    148 			}
    149 		}
    150 		sort.SliceStable(mis, func(i, j int) bool {
    151 			return mis[i].Date > mis[j].Date
    152 		})
    153 		data := strings.TrimSuffix(*data_opt, "/")
    154 		atom, err := os.Create(data + "/atom.xml")
    155 		if err != nil {
    156 			return
    157 		}
    158 		defer atom.Close()
    159 		fmt.Fprintf(atom, `<?xml version='1.0' encoding='UTF-8'?>
    160 <feed xmlns="http://www.w3.org/2005/Atom">
    161   <id>gemini://%s/</id>
    162   <title>%s</title>
    163   <updated>%s</updated>
    164   <author>
    165     <name>%s</name>
    166   </author>
    167   <link href="gemini://%s/atom.xml" rel="self"/>
    168   <link href="gemini://%s/" rel="alternate"/>
    169 `, *url_opt, *title_opt, time.Now().Format(time.RFC3339), *author_opt, *url_opt, *url_opt)
    170 		for _, v := range mis {
    171 			m := v
    172 			if m != nil {
    173 				f, err := os.Create(data + "/" + m.MsgId + ".gmi")
    174 				if err == nil {
    175 					gemini(f, m)
    176 					d := time.Unix(m.Date, 0).Format("2006-01-02")
    177 					fmt.Println("=> /" + m.MsgId + ".gmi " + d + " - " + m.Subj)
    178 				}
    179 				f.Close()
    180 				fmt.Fprintf(atom, `<entry>
    181   <id>gemini://%s/%s.gmi</id>
    182   <title>%s</title>
    183   <updated>%s</updated>
    184   <link href="gemini://%s/%s.gmi" rel="alternate"/>
    185 </entry>
    186 `, *url_opt, m.MsgId, str_esc(m.Subj),
    187 					time.Unix(m.Date, 0).Format(time.RFC3339), *url_opt, m.MsgId)
    188 			}
    189 		}
    190 		fmt.Fprintf(atom, `</feed>
    191 `)
    192 	default:
    193 		fmt.Printf("Wrong cmd: %s\n", cmd)
    194 		os.Exit(1)
    195 	}
    196 }