akyuu/io.go

172 行
4.1 KiB
Go

// $TheSupernovaDuo: akyuu,v master 2023/4/14 21:2:6 yakumo_izuru Exp $
// See LICENSE for copyright details
package main
import (
"bufio"
"errors"
"log"
"os"
"strings"
)
const (
loginsFile = "logins.txt"
feedsDir = "feeds"
ipDelaysFile = "ip_delays.txt"
pwResetFile = "password_reset.txt"
pwResetWaitFile = "password_reset_wait.txt"
)
var (
certPath string
dataDir string
feedsPath string
ipDelaysPath string
keyPath string
loginsPath string
pwResetPath string
pwResetWaitPath string
templPath string
)
func createFileIfNotExists(path string) {
if _, err := os.Stat(path); err != nil {
file, err := os.Create(path)
if err != nil {
log.Fatal("Can't create file: ", err)
}
file.Close()
}
}
func openFile(path string) *os.File {
file, err := os.Open(path)
if err != nil {
file.Close()
log.Fatal("Can't open file for reading", err)
}
return file
}
func linesFromFile(path string) []string {
text, err := os.ReadFile(path)
if err != nil {
log.Fatal("Can't read file", err)
}
if string(text) == "" {
return []string{}
}
return strings.Split(string(text), "\n")
}
func writeAtomic(path, text string) {
tmpFile := path + "_tmp"
if err := os.WriteFile(tmpFile, []byte(text), 0600); err != nil {
log.Fatal("Trouble writing file", err)
}
if err := os.Rename(path, path+"_"); err != nil {
log.Fatal("Trouble moving file", err)
}
if err := os.Rename(tmpFile, path); err != nil {
log.Fatal("Trouble moving file", err)
}
if err := os.Remove(path + "_"); err != nil {
log.Fatal("Trouble removing file", err)
}
}
func writeLinesAtomic(path string, lines []string) {
writeAtomic(path, strings.Join(lines, "\n"))
}
func appendToFile(path string, msg string) {
text, err := os.ReadFile(path)
if err != nil {
log.Fatal("Can't read file", err)
}
writeAtomic(path, string(text)+msg+"\n")
}
func removeLineStartingWith(path, token string) {
lines := linesFromFile(path)
lineNumber := -1
for lineCount := 0; lineCount < len(lines); lineCount += 1 {
line := lines[lineCount]
tokens := strings.Split(line, "\t")
if 0 == strings.Compare(token, tokens[0]) {
lineNumber = lineCount
break
}
}
lines = append(lines[:lineNumber], lines[lineNumber+1:]...)
writeLinesAtomic(path, lines)
}
func removeLineFromFile(path string, lineNumber int) {
lines := linesFromFile(ipDelaysPath)
lines = append(lines[:lineNumber], lines[lineNumber+1:]...)
writeLinesAtomic(path, lines)
}
func replaceLineStartingWith(path, token, newLine string) {
lines := linesFromFile(path)
for i, line := range lines {
tokens := strings.Split(line, "\t")
if 0 == strings.Compare(token, tokens[0]) {
lines[i] = newLine
break
}
}
writeLinesAtomic(path, lines)
}
func tokensFromLine(scanner *bufio.Scanner, nTokensExpected int) []string {
if !scanner.Scan() {
return []string{}
}
line := scanner.Text()
tokens := strings.Split(line, "\t")
if len(tokens) != nTokensExpected {
log.Fatal("Line in file had unexpected number of tokens")
}
return tokens
}
func getFromFileEntryFor(path, token string,
numberTokensExpected int) ([]string, error) {
file := openFile(path)
defer file.Close()
scanner := bufio.NewScanner(bufio.NewReader(file))
tokens := tokensFromLine(scanner, numberTokensExpected)
for 0 != len(tokens) {
if 0 == strings.Compare(tokens[0], token) {
return tokens[1:], nil
}
tokens = tokensFromLine(scanner, numberTokensExpected)
}
return []string{}, errors.New("")
}
func initFilesAndDirs() {
log.Println("Using as templates dir:", templPath)
log.Println("Using as data dir:", dataDir)
loginsPath = dataDir + "/" + loginsFile
feedsPath = dataDir + "/" + feedsDir
ipDelaysPath = dataDir + "/" + ipDelaysFile
pwResetPath = dataDir + "/" + pwResetFile
pwResetWaitPath = dataDir + "/" + pwResetWaitFile
if "" != keyPath {
log.Println("Using TLS.")
if _, err := os.Stat(certPath); err != nil {
log.Fatal("No certificate file found.")
}
if _, err := os.Stat(keyPath); err != nil {
log.Fatal("No server key file found.")
}
}
createFileIfNotExists(loginsPath)
createFileIfNotExists(pwResetPath)
createFileIfNotExists(pwResetWaitPath)
createFileIfNotExists(ipDelaysPath)
_ = os.Mkdir(feedsPath, 0700)
}