2016-12-02 07:38:54 +00:00
|
|
|
package main
|
2017-01-05 14:41:14 +00:00
|
|
|
import "log"
|
2016-12-03 13:45:08 +00:00
|
|
|
import "fmt"
|
|
|
|
import "time"
|
2017-01-05 14:41:14 +00:00
|
|
|
import "os"
|
2017-01-12 02:55:08 +00:00
|
|
|
import "math"
|
|
|
|
import "strings"
|
|
|
|
import "unicode"
|
2016-12-02 07:38:54 +00:00
|
|
|
import "encoding/base64"
|
|
|
|
import "crypto/rand"
|
2017-01-03 07:47:31 +00:00
|
|
|
import "net/smtp"
|
2016-12-02 07:38:54 +00:00
|
|
|
|
|
|
|
// Generate a cryptographically secure set of random bytes..
|
|
|
|
func GenerateSafeString(length int) (string, error) {
|
|
|
|
rb := make([]byte,length)
|
|
|
|
_, err := rand.Read(rb)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return base64.URLEncoding.EncodeToString(rb), nil
|
2016-12-03 13:45:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func relative_time(in string) (string, error) {
|
2017-02-06 04:52:19 +00:00
|
|
|
if in == "" {
|
|
|
|
return "", nil
|
|
|
|
}
|
2016-12-03 13:45:08 +00:00
|
|
|
layout := "2006-01-02 15:04:05"
|
|
|
|
t, err := time.Parse(layout, in)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
diff := time.Since(t)
|
|
|
|
hours := diff.Hours()
|
|
|
|
seconds := diff.Seconds()
|
2017-02-06 04:52:19 +00:00
|
|
|
weeks := int(hours / 24 / 7)
|
|
|
|
months := int(hours / 24 / 31)
|
2016-12-03 13:45:08 +00:00
|
|
|
switch {
|
2017-02-06 04:52:19 +00:00
|
|
|
case months > 11:
|
|
|
|
//return t.Format("Mon Jan 2 2006"), err
|
|
|
|
return t.Format("Jan 2 2006"), err
|
|
|
|
case months > 1:
|
|
|
|
return fmt.Sprintf("%d months ago", months), err
|
|
|
|
case months == 1:
|
|
|
|
return "a month ago", err
|
|
|
|
case weeks > 1:
|
|
|
|
return fmt.Sprintf("%d weeks ago", weeks), err
|
|
|
|
case int(hours / 24) == 7:
|
|
|
|
return "a week ago", err
|
2016-12-03 13:45:08 +00:00
|
|
|
case int(hours / 24) == 1:
|
|
|
|
return "1 day ago", err
|
|
|
|
case int(hours / 24) > 1:
|
|
|
|
return fmt.Sprintf("%d days ago", int(hours / 24)), err
|
|
|
|
case seconds <= 1:
|
|
|
|
return "a moment ago", err
|
|
|
|
case seconds < 60:
|
|
|
|
return fmt.Sprintf("%d seconds ago", int(seconds)), err
|
|
|
|
case seconds < 120:
|
|
|
|
return "a minute ago", err
|
|
|
|
case seconds < 3600:
|
|
|
|
return fmt.Sprintf("%d minutes ago", int(seconds / 60)), err
|
|
|
|
case seconds < 7200:
|
|
|
|
return "an hour ago", err
|
|
|
|
default:
|
|
|
|
return fmt.Sprintf("%d hours ago", int(seconds / 60 / 60)), err
|
|
|
|
}
|
2017-01-03 07:47:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func SendEmail(email string, subject string, msg string) bool {
|
|
|
|
// This hook is useful for plugin_sendmail or for testing tools. Possibly to hook it into some sort of mail server?
|
|
|
|
if vhooks["email_send_intercept"] != nil {
|
|
|
|
return vhooks["email_send_intercept"](email, subject, msg).(bool)
|
|
|
|
}
|
|
|
|
body := "Subject: " + subject + "\n\n" + msg + "\n"
|
|
|
|
|
2017-03-16 05:06:58 +00:00
|
|
|
con, err := smtp.Dial(smtp_server + ":" + smtp_port)
|
2017-01-03 07:47:31 +00:00
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-03-16 05:06:58 +00:00
|
|
|
if smtp_username != "" {
|
|
|
|
auth := smtp.PlainAuth("",smtp_username,smtp_password,smtp_server)
|
|
|
|
err = con.Auth(auth)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-03 07:47:31 +00:00
|
|
|
err = con.Mail(site_email)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
err = con.Rcpt(email)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
email_data, err := con.Data()
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
_, err = fmt.Fprintf(email_data, body)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
err = email_data.Close()
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
err = con.Quit()
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
2017-01-05 14:41:14 +00:00
|
|
|
|
|
|
|
func write_file(name string, content string) {
|
|
|
|
f, err := os.Create(name)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
_, err = f.WriteString(content)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
f.Sync()
|
|
|
|
f.Close()
|
|
|
|
}
|
2017-01-12 02:55:08 +00:00
|
|
|
|
2017-01-12 14:01:35 +00:00
|
|
|
func word_count(input string) (count int) {
|
2017-01-12 02:55:08 +00:00
|
|
|
input = strings.TrimSpace(input)
|
2017-02-10 13:39:13 +00:00
|
|
|
if input == "" {
|
|
|
|
return 0
|
|
|
|
}
|
2017-01-12 02:55:08 +00:00
|
|
|
in_space := false
|
|
|
|
for _, value := range input {
|
|
|
|
if unicode.IsSpace(value) {
|
|
|
|
if !in_space {
|
|
|
|
in_space = true
|
|
|
|
}
|
|
|
|
} else if in_space {
|
|
|
|
count++
|
|
|
|
in_space = false
|
|
|
|
}
|
|
|
|
}
|
2017-02-10 13:39:13 +00:00
|
|
|
return count + 1
|
2017-01-12 02:55:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getLevel(score int) (level int) {
|
|
|
|
var base float64 = 25
|
|
|
|
var current float64
|
|
|
|
var prev float64
|
|
|
|
exp_factor := 2.8
|
|
|
|
|
|
|
|
for i := 1;;i++ {
|
|
|
|
_, bit := math.Modf(float64(i) / 10)
|
|
|
|
if bit == 0 {
|
|
|
|
exp_factor += 0.1
|
|
|
|
}
|
|
|
|
current = base + math.Pow(float64(i), exp_factor) + (prev / 3)
|
|
|
|
prev = current
|
|
|
|
if float64(score) < current {
|
|
|
|
break
|
|
|
|
}
|
2017-02-04 06:19:55 +00:00
|
|
|
level++
|
2017-01-12 02:55:08 +00:00
|
|
|
}
|
|
|
|
return level
|
|
|
|
}
|
|
|
|
|
|
|
|
func getLevelScore(getLevel int) (score int) {
|
|
|
|
var base float64 = 25
|
|
|
|
var current float64
|
|
|
|
var prev float64
|
|
|
|
var level int
|
|
|
|
exp_factor := 2.8
|
|
|
|
|
|
|
|
for i := 1;;i++ {
|
|
|
|
_, bit := math.Modf(float64(i) / 10)
|
|
|
|
if bit == 0 {
|
|
|
|
exp_factor += 0.1
|
|
|
|
}
|
|
|
|
current = base + math.Pow(float64(i), exp_factor) + (prev / 3)
|
|
|
|
prev = current
|
|
|
|
level++
|
|
|
|
if level <= getLevel {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return int(math.Ceil(current))
|
|
|
|
}
|
|
|
|
|
|
|
|
func getLevels(maxLevel int) []float64 {
|
|
|
|
var base float64 = 25
|
|
|
|
var current float64 = 0
|
|
|
|
var prev float64 = 0
|
|
|
|
exp_factor := 2.8
|
|
|
|
var out []float64
|
|
|
|
out = append(out, 0)
|
|
|
|
|
|
|
|
for i := 1;i <= maxLevel;i++ {
|
|
|
|
_, bit := math.Modf(float64(i) / 10)
|
|
|
|
if bit == 0 {
|
|
|
|
exp_factor += 0.1
|
|
|
|
}
|
|
|
|
current = base + math.Pow(float64(i), exp_factor) + (prev / 3)
|
|
|
|
prev = current
|
|
|
|
out = append(out, current)
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|
2017-01-26 13:37:50 +00:00
|
|
|
|
|
|
|
func fill_forum_id_gap(biggerID int, smallerID int) {
|
2017-02-04 15:49:24 +00:00
|
|
|
dummy := Forum{ID:0,Name:"",Active:false,Preset:"all"}
|
2017-01-26 13:37:50 +00:00
|
|
|
for i := smallerID; i > biggerID;i++ {
|
|
|
|
forums = append(forums, dummy)
|
|
|
|
}
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func fill_group_id_gap(biggerID int, smallerID int) {
|
|
|
|
dummy := Group{ID:0, Name:""}
|
|
|
|
for i := smallerID; i > biggerID;i++ {
|
|
|
|
groups = append(groups, dummy)
|
|
|
|
}
|
|
|
|
}
|
2017-04-05 14:05:37 +00:00
|
|
|
|
|
|
|
func addModLog(action string, elementID int, elementType string, ipaddress string, actorID int) error {
|
|
|
|
_, err := add_modlog_entry_stmt.Exec(action,elementID,elementType,ipaddress,actorID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func addAdminLog(action string, elementID string, elementType int, ipaddress string, actorID int) error {
|
|
|
|
_, err := add_adminlog_entry_stmt.Exec(action,elementID,elementType,ipaddress,actorID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|