Browse Source
More destruction. Utils too, since they cause weird go mod shenanigans.
thegreatrefactor
More destruction. Utils too, since they cause weird go mod shenanigans.
thegreatrefactor
Gisle Aune
5 years ago
20 changed files with 0 additions and 874 deletions
-
5Dockerfile
-
139cmd/rpdata-as2storyimport/main.go
-
41cmd/rpdata-ensurechannels/main.go
-
3cmd/rpdata-lb2charimport/.gitignore
-
55cmd/rpdata-lb2charimport/data.go
-
62cmd/rpdata-lb2charimport/main.go
-
2cmd/rpdata-lb2logimport/.gitignore
-
85cmd/rpdata-lb2logimport/line.go
-
110cmd/rpdata-lb2logimport/main.go
-
77cmd/rpdata-wikifileimport/main.go
-
6go.mod
-
12go.sum
-
83models/files/db.go
-
16models/files/find.go
-
29models/files/insert.go
-
36models/files/list.go
-
52models/files/upload.go
-
14models/users/db.go
-
34models/users/ensure.go
-
13models/users/find.go
@ -1,139 +0,0 @@ |
|||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"flag" |
|
||||
"fmt" |
|
||||
"log" |
|
||||
"strings" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/internal/store" |
|
||||
"git.aiterp.net/rpdata/api/models" |
|
||||
"git.aiterp.net/rpdata/api/models/chapters" |
|
||||
"git.aiterp.net/rpdata/api/models/stories" |
|
||||
_ "github.com/go-sql-driver/mysql" |
|
||||
"github.com/jmoiron/sqlx" |
|
||||
) |
|
||||
|
|
||||
var flagHost = flag.String("host", "127.0.0.1:3306", "SQL host") |
|
||||
var flagDB = flag.String("database", "aitestory", "SQL database") |
|
||||
var flagUser = flag.String("user", "aitestory", "SQL user") |
|
||||
var flagPassword = flag.String("password", "", "SQL password") |
|
||||
|
|
||||
func main() { |
|
||||
flag.Parse() |
|
||||
|
|
||||
db, err := sqlx.Connect("mysql", fmt.Sprintf("%s:%s@(%s)/%s", *flagUser, *flagPassword, *flagHost, *flagDB)) |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
err = db.Ping() |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
store.Init() |
|
||||
|
|
||||
results := make([]storyResult, 0, 64) |
|
||||
rows, err := db.Queryx("SELECT * FROM page WHERE unlisted=0;") |
|
||||
for rows.Next() { |
|
||||
result := storyResult{} |
|
||||
err := rows.StructScan(&result) |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
results = append(results, result) |
|
||||
} |
|
||||
|
|
||||
tagResults := make([]tagResult, 0, 256) |
|
||||
rows, err = db.Queryx("SELECT page_id,type,name FROM page_tag LEFT JOIN tag ON tag_id=tag.id;") |
|
||||
for rows.Next() { |
|
||||
result := tagResult{} |
|
||||
err := rows.StructScan(&result) |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
tagResults = append(tagResults, result) |
|
||||
} |
|
||||
|
|
||||
for _, result := range results { |
|
||||
fictionalDate, err := time.Parse("2006-01-02 15:04:05", result.FictionalDate) |
|
||||
if err != nil { |
|
||||
if result.FictionalDate != "0000-00-00 00:00:00" { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
} |
|
||||
if fictionalDate.Year() < 1800 { |
|
||||
fictionalDate = time.Time{} |
|
||||
} |
|
||||
|
|
||||
publishDate, err := time.Parse("2006-01-02 15:04:05", result.PublishDate) |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
tags := make([]models.Tag, 0, 8) |
|
||||
for _, tagResult := range tagResults { |
|
||||
if tagResult.PageID == result.ID { |
|
||||
tags = append(tags, models.Tag{Kind: models.TagKind(tagResult.Type), Name: tagResult.Name}) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
category := models.StoryCategory(result.Category) |
|
||||
if !category.IsValid() { |
|
||||
log.Println(result.Name, "does not have a valid category:", result.Category) |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
story, err := stories.Add(result.Name, result.Author[5:], category, true, false, tags, publishDate, fictionalDate) |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
// Change the story title
|
|
||||
title := result.Name |
|
||||
if strings.HasPrefix(result.Source, "#") { |
|
||||
firstNewline := strings.Index(result.Source, "\n") |
|
||||
result.Name = strings.Replace(result.Source[1:firstNewline], "\r", "", -1) |
|
||||
result.Source = result.Source[firstNewline+1:] |
|
||||
|
|
||||
result.Source = strings.Replace(result.Source, "\r\n", "\n", -1) |
|
||||
if strings.HasPrefix(result.Source, "\r") || strings.HasPrefix(result.Source, "\n") { |
|
||||
result.Source = result.Source[1:] |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
chapter, err := chapters.Add(story, title, result.Author[5:], result.Source, publishDate, &fictionalDate, models.ChapterCommentModeDisabled) |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
fmt.Println(result.ID, "->", story.ID, chapter.ID) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
type tagResult struct { |
|
||||
PageID string `db:"page_id"` |
|
||||
Type string `db:"type"` |
|
||||
Name string `db:"name"` |
|
||||
} |
|
||||
|
|
||||
type storyResult struct { |
|
||||
ID string `db:"id"` |
|
||||
Name string `db:"name"` |
|
||||
Author string `db:"author"` |
|
||||
Category string `db:"category"` |
|
||||
FictionalDate string `db:"fictional_date"` |
|
||||
PublishDate string `db:"publish_date"` |
|
||||
EditDate string `db:"edit_date"` |
|
||||
Unlisted bool `db:"unlisted"` |
|
||||
Dated bool `db:"dated"` |
|
||||
Spesific bool `db:"specific"` |
|
||||
Indexed bool `db:"indexed"` |
|
||||
Published bool `db:"published"` |
|
||||
Type string `db:"type"` |
|
||||
Source string `db:"source"` |
|
||||
Cache string `db:"cache"` |
|
||||
BackgroundURL *string `db:"background_url"` |
|
||||
} |
|
@ -1,41 +0,0 @@ |
|||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"fmt" |
|
||||
"os" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/internal/store" |
|
||||
"git.aiterp.net/rpdata/api/models/channels" |
|
||||
"git.aiterp.net/rpdata/api/models/logs" |
|
||||
) |
|
||||
|
|
||||
func main() { |
|
||||
err := store.Init() |
|
||||
if err != nil { |
|
||||
fmt.Fprintln(os.Stderr, err) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
logs, err := logs.List(nil) |
|
||||
if err != nil { |
|
||||
fmt.Fprintln(os.Stderr, err) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
added := make(map[string]bool, 1024) |
|
||||
for _, log := range logs { |
|
||||
if added[log.ChannelName] { |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
_, err := channels.Ensure(log.ChannelName, false) |
|
||||
if err != nil { |
|
||||
fmt.Fprintln(os.Stderr, log.ID, err) |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
added[log.ChannelName] = true |
|
||||
|
|
||||
fmt.Println(log.ChannelName, "ensured") |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
characters.json |
|
||||
characters.cson |
|
||||
debug |
|
@ -1,55 +0,0 @@ |
|||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"encoding/json" |
|
||||
"io" |
|
||||
"strings" |
|
||||
) |
|
||||
|
|
||||
type charInfo struct { |
|
||||
Nicks []string `json:"nicks"` |
|
||||
Name string `json:"name"` |
|
||||
Author string `json:"player"` |
|
||||
ShortName string `json:"first"` |
|
||||
} |
|
||||
|
|
||||
func load(reader io.Reader) ([]charInfo, error) { |
|
||||
data := make(map[string]interface{}) |
|
||||
err := json.NewDecoder(reader).Decode(&data) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
links := make(map[string]string, len(data)) |
|
||||
infos := make([]charInfo, 0, 64) |
|
||||
|
|
||||
for key, value := range data { |
|
||||
if info, ok := value.(map[string]interface{}); ok { |
|
||||
name := info["name"].(string) |
|
||||
author := info["player"].(string) |
|
||||
shortName, ok := info["first"].(string) |
|
||||
if !ok { |
|
||||
shortName = strings.SplitN(name, " ", 2)[0] |
|
||||
} |
|
||||
|
|
||||
infos = append(infos, charInfo{ |
|
||||
Nicks: []string{key}, |
|
||||
Name: name, |
|
||||
Author: author, |
|
||||
ShortName: shortName, |
|
||||
}) |
|
||||
} else if nick, ok := value.(string); ok { |
|
||||
links[key] = nick |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
for key, value := range links { |
|
||||
for i := range infos { |
|
||||
if infos[i].Nicks[0] == value { |
|
||||
infos[i].Nicks = append(infos[i].Nicks, key) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return infos, nil |
|
||||
} |
|
@ -1,62 +0,0 @@ |
|||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"flag" |
|
||||
"log" |
|
||||
"os" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/internal/store" |
|
||||
"git.aiterp.net/rpdata/api/models/characters" |
|
||||
) |
|
||||
|
|
||||
var fileName = flag.String("file", "./characters.json", "json file to load") |
|
||||
|
|
||||
func main() { |
|
||||
file, err := os.Open(*fileName) |
|
||||
if err != nil { |
|
||||
log.Fatalln("Open:", err) |
|
||||
} |
|
||||
|
|
||||
infos, err := load(file) |
|
||||
if err != nil { |
|
||||
log.Fatalln("Parse:", err) |
|
||||
} |
|
||||
|
|
||||
err = store.Init() |
|
||||
if err != nil { |
|
||||
log.Fatalln("Store:", err) |
|
||||
} |
|
||||
|
|
||||
charsAdded, charsFailed := 0, 0 |
|
||||
nicksAdded, nicksFailed := 0, 0 |
|
||||
|
|
||||
for _, info := range infos { |
|
||||
char, err := characters.Add(info.Nicks[0], info.Name, info.ShortName, info.Author, "") |
|
||||
if err != nil { |
|
||||
log.Println(info.Nicks[0], "failed to insert:", err) |
|
||||
charsFailed++ |
|
||||
|
|
||||
char, err = characters.FindNick(info.Nicks[0]) |
|
||||
if err != nil { |
|
||||
continue |
|
||||
} |
|
||||
} else { |
|
||||
log.Println(info.Nicks[0], "added") |
|
||||
charsAdded++ |
|
||||
} |
|
||||
|
|
||||
for _, alt := range info.Nicks[1:] { |
|
||||
char, err = characters.AddNick(char, alt) |
|
||||
if err != nil { |
|
||||
log.Println(info.Nicks[0], "failed to add nick", alt, "error:", err) |
|
||||
nicksFailed++ |
|
||||
} else { |
|
||||
log.Println(info.Nicks[0], "addded nick", alt) |
|
||||
nicksAdded++ |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
log.Printf("Characters – %d/%d", charsAdded, charsFailed+charsAdded) |
|
||||
log.Printf("Alt. Nicks – %d/%d", nicksAdded, nicksFailed+nicksAdded) |
|
||||
} |
|
@ -1,2 +0,0 @@ |
|||||
logs |
|
||||
debug |
|
@ -1,85 +0,0 @@ |
|||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"bufio" |
|
||||
"errors" |
|
||||
"io" |
|
||||
"strconv" |
|
||||
"strings" |
|
||||
"time" |
|
||||
) |
|
||||
|
|
||||
type logLine struct { |
|
||||
Verb string |
|
||||
Args []string |
|
||||
Text string |
|
||||
} |
|
||||
|
|
||||
func parseFile(reader io.Reader) []logLine { |
|
||||
bufReader := bufio.NewReader(reader) |
|
||||
results := make([]logLine, 0, 512) |
|
||||
|
|
||||
for { |
|
||||
line, err := bufReader.ReadString('\n') |
|
||||
if err == io.EOF { |
|
||||
if len(line) < 2 { |
|
||||
break |
|
||||
} |
|
||||
} else if err != nil { |
|
||||
break |
|
||||
} |
|
||||
|
|
||||
if len(line) <= 2 { |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
line = strings.Replace(line, "\n", "", 1) |
|
||||
line = strings.Replace(line, "\r", "", 1) |
|
||||
|
|
||||
results = append(results, parseLine(line)) |
|
||||
} |
|
||||
|
|
||||
return results |
|
||||
} |
|
||||
|
|
||||
func parseLine(line string) logLine { |
|
||||
textSplit := strings.SplitN(line, " :", 2) |
|
||||
tokens := strings.Split(textSplit[0], " ") |
|
||||
|
|
||||
ll := logLine{ |
|
||||
Verb: tokens[0], |
|
||||
} |
|
||||
|
|
||||
if len(tokens) > 1 { |
|
||||
ll.Args = tokens[1:] |
|
||||
} |
|
||||
|
|
||||
if len(textSplit) > 1 { |
|
||||
ll.Text = textSplit[1] |
|
||||
} |
|
||||
|
|
||||
return ll |
|
||||
} |
|
||||
|
|
||||
func parseFilename(fname string) (date time.Time, channel string, err error) { |
|
||||
date, err = time.ParseInLocation("2006-01-02_150405", fname[:17], time.Local) |
|
||||
if err != nil { |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
ms, err := strconv.Atoi(fname[17:20]) |
|
||||
if err != nil { |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
date = date.Add(time.Duration(ms) * time.Millisecond) |
|
||||
|
|
||||
if len(fname) < 23 { |
|
||||
err = errors.New("filename too short") |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
channel = fname[21:] |
|
||||
|
|
||||
return |
|
||||
} |
|
@ -1,110 +0,0 @@ |
|||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"fmt" |
|
||||
"log" |
|
||||
"os" |
|
||||
"path" |
|
||||
"strings" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/models/posts" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/internal/store" |
|
||||
"git.aiterp.net/rpdata/api/models/logs" |
|
||||
) |
|
||||
|
|
||||
var prefixReplacer = strings.NewReplacer("+", "", "@", "", "!", "", "%", "") |
|
||||
|
|
||||
func main() { |
|
||||
err := store.Init() |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
for _, filepath := range os.Args[1:] { |
|
||||
name := strings.Replace(path.Base(filepath), ".txt", "", 1) |
|
||||
file, err := os.Open(filepath) |
|
||||
if err != nil { |
|
||||
log.Println(filepath, err) |
|
||||
continue |
|
||||
} |
|
||||
logLines := parseFile(file) |
|
||||
file.Close() |
|
||||
|
|
||||
// Get title and event
|
|
||||
title := "" |
|
||||
event := "" |
|
||||
for _, line := range logLines { |
|
||||
if line.Verb == "TITLE" { |
|
||||
title = line.Text |
|
||||
} |
|
||||
if line.Verb == "TAG" { |
|
||||
event = line.Text |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
date, channel, err := parseFilename(name) |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
l, err := logs.Add(date, channel, title, event, "", false) |
|
||||
if err != nil { |
|
||||
log.Println(err) |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
_, err = posts.Add(l, time.Now(), "annotation.info", "rpdata-lb2logimport", "This logfile is imported from aitelogs2 and may contain errors or wrong timestamps.") |
|
||||
if err != nil { |
|
||||
log.Println(err) |
|
||||
} |
|
||||
|
|
||||
for _, line := range logLines { |
|
||||
if line.Verb != "CHARS" { |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
_, err = posts.Add(l, l.Date, "chars", prefixReplacer.Replace(line.Args[0]), line.Text) |
|
||||
if err != nil { |
|
||||
log.Println(err) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
for _, line := range logLines { |
|
||||
if line.Verb != "SCENE" && line.Verb != "ACTION" && line.Verb != "TEXT" { |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
postTime, err := time.ParseInLocation("2006-01-02 15:04:05", date.Format("2006-01-02")+" "+line.Args[1], time.Local) |
|
||||
diff := postTime.Sub(date) |
|
||||
if err != nil { |
|
||||
log.Println(err) |
|
||||
continue |
|
||||
} |
|
||||
if diff < 0 { |
|
||||
if diff > -time.Second { |
|
||||
postTime = postTime.Add(diff) |
|
||||
} else { |
|
||||
postTime = postTime.Add(time.Hour * 24) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if line.Args[0][0] == '=' { |
|
||||
line.Verb = "SCENE" |
|
||||
} |
|
||||
|
|
||||
_, err = posts.Add(l, postTime, strings.ToLower(line.Verb), prefixReplacer.Replace(line.Args[0]), line.Text) |
|
||||
if err != nil { |
|
||||
log.Println(err) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
l, err = logs.UpdateCharacters(l, nil) |
|
||||
if err != nil { |
|
||||
log.Println(err) |
|
||||
} |
|
||||
|
|
||||
fmt.Println(l.ID, "completed") |
|
||||
} |
|
||||
} |
|
@ -1,77 +0,0 @@ |
|||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"encoding/json" |
|
||||
"fmt" |
|
||||
"log" |
|
||||
"net/http" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/internal/config" |
|
||||
"git.aiterp.net/rpdata/api/internal/store" |
|
||||
"git.aiterp.net/rpdata/api/models/files" |
|
||||
) |
|
||||
|
|
||||
func main() { |
|
||||
client := http.Client{Timeout: time.Second * 30} |
|
||||
|
|
||||
res, err := client.Get(config.Global().Wiki.URL + "?action=query&list=allimages&ailimit=5&aiprop=dimensions|mime|url|user|timestamp&format=json&ailimit=500") |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
if res.StatusCode != 200 { |
|
||||
log.Fatalln(res.Status) |
|
||||
} |
|
||||
|
|
||||
data := ResponseData{} |
|
||||
err = json.NewDecoder(res.Body).Decode(&data) |
|
||||
if err != nil { |
|
||||
log.Fatalln(err) |
|
||||
} |
|
||||
|
|
||||
store.Init() |
|
||||
|
|
||||
for _, info := range data.Query.Allimages { |
|
||||
existing, err := files.FindName("wiki", info.Name, info.User) |
|
||||
if err == nil && existing.ID != "" { |
|
||||
log.Println("Skipping", info.Name, "because it already exists") |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
ts, err := time.Parse(time.RFC3339, info.Timestamp) |
|
||||
if err != nil { |
|
||||
log.Println("Skipping", info.Name, "error:", err) |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
file, err := files.Insert(info.Name, "wiki", info.Mime, info.User, ts, info.Size, info.URL) |
|
||||
if err != nil { |
|
||||
log.Println("Skipping", info.Name, "error:", err) |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
fmt.Println(file.Name, "inserted ( id:", file.ID, ")") |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// The ResponseData from the wiki looks like this
|
|
||||
type ResponseData struct { |
|
||||
Batchcomplete string `json:"batchcomplete"` |
|
||||
Query struct { |
|
||||
Allimages []struct { |
|
||||
Descriptionshorturl string `json:"descriptionshorturl"` |
|
||||
Descriptionurl string `json:"descriptionurl"` |
|
||||
Height int `json:"height"` |
|
||||
Mime string `json:"mime"` |
|
||||
Name string `json:"name"` |
|
||||
Ns int `json:"ns"` |
|
||||
Size int64 `json:"size"` |
|
||||
Timestamp string `json:"timestamp"` |
|
||||
Title string `json:"title"` |
|
||||
URL string `json:"url"` |
|
||||
User string `json:"user"` |
|
||||
Width int `json:"width"` |
|
||||
} `json:"allimages"` |
|
||||
} `json:"query"` |
|
||||
} |
|
@ -1,83 +0,0 @@ |
|||||
package files |
|
||||
|
|
||||
import ( |
|
||||
"crypto/rand" |
|
||||
"encoding/binary" |
|
||||
"strconv" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/internal/store" |
|
||||
"git.aiterp.net/rpdata/api/models" |
|
||||
"github.com/globalsign/mgo" |
|
||||
) |
|
||||
|
|
||||
var collection *mgo.Collection |
|
||||
|
|
||||
func find(query interface{}) (models.File, error) { |
|
||||
file := models.File{} |
|
||||
|
|
||||
err := collection.Find(query).One(&file) |
|
||||
if err != nil { |
|
||||
return models.File{}, err |
|
||||
} |
|
||||
|
|
||||
return file, nil |
|
||||
} |
|
||||
|
|
||||
func list(query interface{}) ([]models.File, error) { |
|
||||
list := make([]models.File, 0, 32) |
|
||||
|
|
||||
err := collection.Find(query).Sort("-time").All(&list) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return list, nil |
|
||||
} |
|
||||
|
|
||||
// makeID makes a random file ID that's 32 characters long
|
|
||||
func makeID() string { |
|
||||
result := "F" + strconv.FormatInt(time.Now().UnixNano(), 36) |
|
||||
offset := 0 |
|
||||
data := make([]byte, 32) |
|
||||
|
|
||||
rand.Read(data) |
|
||||
for len(result) < 32 { |
|
||||
result += strconv.FormatUint(binary.LittleEndian.Uint64(data[offset:]), 36) |
|
||||
offset += 8 |
|
||||
|
|
||||
if offset >= 32 { |
|
||||
rand.Read(data) |
|
||||
offset = 0 |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return result[:32] |
|
||||
} |
|
||||
|
|
||||
func init() { |
|
||||
store.HandleInit(func(db *mgo.Database) { |
|
||||
collection = db.C("file.headers") |
|
||||
|
|
||||
collection.EnsureIndexKey("author") |
|
||||
collection.EnsureIndexKey("public") |
|
||||
collection.EnsureIndexKey("kind", "name", "author") |
|
||||
collection.EnsureIndexKey("author", "public") |
|
||||
collection.EnsureIndexKey("kind") |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
var allowdMimeTypes = map[string]bool{ |
|
||||
"": false, |
|
||||
"image/jpeg": true, |
|
||||
"image/png": true, |
|
||||
"image/gif": true, |
|
||||
"image/tiff": true, |
|
||||
"image/tga": true, |
|
||||
"text/plain": true, |
|
||||
"application/json": true, |
|
||||
"application/pdf": false, |
|
||||
"binary/octet-stream": false, |
|
||||
"video/mp4": false, |
|
||||
"audio/mp3": false, |
|
||||
} |
|
@ -1,16 +0,0 @@ |
|||||
package files |
|
||||
|
|
||||
import ( |
|
||||
"git.aiterp.net/rpdata/api/models" |
|
||||
"github.com/globalsign/mgo/bson" |
|
||||
) |
|
||||
|
|
||||
// FindID finds a file by ID
|
|
||||
func FindID(id string) (models.File, error) { |
|
||||
return find(bson.M{"_id": id}) |
|
||||
} |
|
||||
|
|
||||
// FindName finds a file by ID
|
|
||||
func FindName(kind, name, author string) (models.File, error) { |
|
||||
return find(bson.M{"name": name, "kind": kind, "author": author}) |
|
||||
} |
|
@ -1,29 +0,0 @@ |
|||||
package files |
|
||||
|
|
||||
import ( |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/models" |
|
||||
) |
|
||||
|
|
||||
// Insert manually inserts file information into the database. This should never, ever be HTTP API accessible
|
|
||||
func Insert(name, kind, mimeType, author string, time time.Time, size int64, url string) (models.File, error) { |
|
||||
file := models.File{ |
|
||||
ID: makeID(), |
|
||||
Kind: kind, |
|
||||
Time: time, |
|
||||
Public: false, |
|
||||
Author: author, |
|
||||
Name: name, |
|
||||
MimeType: mimeType, |
|
||||
Size: size, |
|
||||
URL: url, |
|
||||
} |
|
||||
|
|
||||
err := collection.Insert(file) |
|
||||
if err != nil { |
|
||||
return models.File{}, err |
|
||||
} |
|
||||
|
|
||||
return file, nil |
|
||||
} |
|
@ -1,36 +0,0 @@ |
|||||
package files |
|
||||
|
|
||||
import ( |
|
||||
"git.aiterp.net/rpdata/api/models" |
|
||||
"github.com/globalsign/mgo/bson" |
|
||||
) |
|
||||
|
|
||||
// Filter for files.List
|
|
||||
type Filter struct { |
|
||||
Author *string |
|
||||
Public *bool |
|
||||
MimeType []string |
|
||||
} |
|
||||
|
|
||||
// List lists files according to the standard lookup. By default it's just the author's own files,
|
|
||||
// but if `public` is true it will alos include files made public by other authors. If `mimeTypes` contains
|
|
||||
// any, it will limit the results to that. If `author` is empty, it will only list public files
|
|
||||
func List(filter *Filter) ([]models.File, error) { |
|
||||
query := bson.M{} |
|
||||
|
|
||||
if filter != nil { |
|
||||
if filter.Author != nil { |
|
||||
query["author"] = *filter.Author |
|
||||
} |
|
||||
|
|
||||
if filter.Public != nil { |
|
||||
query["public"] = *filter.Public |
|
||||
} |
|
||||
|
|
||||
if len(filter.MimeType) > 0 { |
|
||||
query["mimeTypes"] = bson.M{"$in": filter.MimeType} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return list(query) |
|
||||
} |
|
@ -1,52 +0,0 @@ |
|||||
package files |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"errors" |
|
||||
"io" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/internal/store" |
|
||||
"git.aiterp.net/rpdata/api/models" |
|
||||
) |
|
||||
|
|
||||
// Upload adds a file to the space.
|
|
||||
func Upload(ctx context.Context, name, mimeType, author string, size int64, input io.Reader) (models.File, error) { |
|
||||
if !allowdMimeTypes[mimeType] { |
|
||||
return models.File{}, errors.New("File type not allowed:" + mimeType) |
|
||||
} |
|
||||
|
|
||||
if name == "" { |
|
||||
date := time.Now().UTC().Format("Jan 02 2006 15:04:05 MST") |
|
||||
name = "Unnamed file (" + date + ")" |
|
||||
} |
|
||||
if mimeType == "" { |
|
||||
mimeType = "binary/octet-stream" |
|
||||
} |
|
||||
|
|
||||
id := makeID() |
|
||||
|
|
||||
path, err := store.UploadFile(ctx, "files", id, mimeType, input, size) |
|
||||
if err != nil { |
|
||||
return models.File{}, err |
|
||||
} |
|
||||
|
|
||||
file := models.File{ |
|
||||
ID: id, |
|
||||
Kind: "upload", |
|
||||
Time: time.Now(), |
|
||||
Public: false, |
|
||||
Author: author, |
|
||||
Name: name, |
|
||||
MimeType: mimeType, |
|
||||
Size: size, |
|
||||
URL: store.URLFromPath(path), |
|
||||
} |
|
||||
|
|
||||
err = collection.Insert(file) |
|
||||
if err != nil { |
|
||||
return models.File{}, err |
|
||||
} |
|
||||
|
|
||||
return file, nil |
|
||||
} |
|
@ -1,14 +0,0 @@ |
|||||
package users |
|
||||
|
|
||||
import ( |
|
||||
"git.aiterp.net/rpdata/api/internal/store" |
|
||||
"github.com/globalsign/mgo" |
|
||||
) |
|
||||
|
|
||||
var collection *mgo.Collection |
|
||||
|
|
||||
func init() { |
|
||||
store.HandleInit(func(db *mgo.Database) { |
|
||||
collection = db.C("core.users") |
|
||||
}) |
|
||||
} |
|
@ -1,34 +0,0 @@ |
|||||
package users |
|
||||
|
|
||||
import ( |
|
||||
"git.aiterp.net/rpdata/api/models" |
|
||||
"github.com/globalsign/mgo" |
|
||||
) |
|
||||
|
|
||||
// Ensure finds a user by id, or makes a new one.
|
|
||||
func Ensure(id string) (models.User, error) { |
|
||||
user := models.User{} |
|
||||
err := collection.FindId(id).One(&user) |
|
||||
|
|
||||
if err == mgo.ErrNotFound { |
|
||||
user = models.User{ |
|
||||
ID: id, |
|
||||
Nick: "", |
|
||||
Permissions: []string{ |
|
||||
"member", |
|
||||
"log.edit", |
|
||||
"post.edit", |
|
||||
"post.move", |
|
||||
"post.remove", |
|
||||
"file.upload", |
|
||||
}, |
|
||||
} |
|
||||
|
|
||||
err := collection.Insert(user) |
|
||||
if err != nil { |
|
||||
return models.User{}, err |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return user, err |
|
||||
} |
|
@ -1,13 +0,0 @@ |
|||||
package users |
|
||||
|
|
||||
import ( |
|
||||
"git.aiterp.net/rpdata/api/models" |
|
||||
) |
|
||||
|
|
||||
// Find finds a user by id
|
|
||||
func Find(id string) (models.User, error) { |
|
||||
user := models.User{} |
|
||||
err := collection.FindId(id).One(&user) |
|
||||
|
|
||||
return user, err |
|
||||
} |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue