update install

This commit is contained in:
aichy 2022-09-28 16:24:33 +08:00
parent 0fe709d84b
commit 27f05ee63c
11 changed files with 353 additions and 14 deletions

View File

@ -27,10 +27,11 @@ COPY --from=node-builder /tmp/build ${BUILD_DIR}/web/html
CMD ls -al ${BUILD_DIR}/web/html
RUN make clean build && \
cp answer /usr/bin/answer && \
cp configs/config.yaml /etc/config.yaml && \
mkdir -p /tmp/cache && chmod 777 /tmp/cache && \
mkdir /data && chmod 777 /data && cp configs/config.yaml /data && \
mkdir -p /data/upfiles && chmod 777 /data/upfiles && cp -r i18n /data
FROM debian:bullseye
ENV TZ "Asia/Shanghai"
@ -45,9 +46,8 @@ RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.li
COPY --from=golang-builder /data /data
VOLUME /data
COPY --from=golang-builder /etc/config.yaml /etc/answer.yaml
COPY --from=golang-builder /usr/bin/answer /usr/bin/answer
EXPOSE 80
ENTRYPOINT ["dumb-init", "/usr/bin/answer", "-c", "/etc/answer.yaml"]
CMD ["/usr/bin/answer", "init"]
ENTRYPOINT ["dumb-init", "/usr/bin/answer", "-c", "/data/config.yaml"]

View File

@ -0,0 +1,19 @@
server:
http:
addr: 0.0.0.0:80
data:
database:
connection: root:root@tcp(127.0.0.1:3306)/answer
cache:
file_path: "/tmp/cache/cache.db"
i18n:
bundle_dir: "/data/i18n"
swaggerui:
show: false
protocol: http
host: 127.0.0.1
address: ':80'
service_config:
secret_key: "answer"
web_host: "http://127.0.0.1"
upload_path: "./upfiles"

View File

@ -0,0 +1,160 @@
base:
success:
other: "success"
unknown:
other: "unknown error"
request_format_error:
other: "request format is not valid"
unauthorized_error:
other: "unauthorized"
database_error:
other: "data server error"
email:
other: "email"
password:
other: "password"
email_or_password_wrong_error: &email_or_password_wrong
other: "email or password wrong"
error:
admin:
email_or_password_wrong: *email_or_password_wrong
answer:
not_found:
other: "answer not found"
comment:
edit_without_permission:
other: "comment not allowed to edit"
not_found:
other: "comment not found"
email:
duplicate:
other: "email already exists"
need_to_be_verified:
other: "email should be verified"
verify_url_expired:
other: "email verified url is expired, please resend the email"
lang:
not_found:
other: "language not found"
object:
captcha_verification_failed:
other: "captcha wrong"
disallow_follow:
other: "You are not allowed to follow"
disallow_vote:
other: "You are not allowed to vote"
disallow_vote_your_self:
other: "You can't vote for your own post!"
not_found:
other: "object not found"
question:
not_found:
other: "question not found"
rank:
fail_to_meet_the_condition:
other: "rank fail to meet the condition"
report:
handle_failed:
other: "report handle failed"
not_found:
other: "report not found"
tag:
not_found:
other: "tag not found"
theme:
not_found:
other: "theme not found"
user:
email_or_password_wrong:
other: *email_or_password_wrong
not_found:
other: "user not found"
suspended:
other: "user is suspended"
report:
spam:
name:
other: "spam"
description:
other: "This post is an advertisement,or vandalism.It is not useful or relevant to the current topic."
rude:
name:
other: "rude or abusive"
description:
other: "A reasonable person would find this content inappropriate for respectful discourse."
duplicate:
name:
other: "a duplicate"
description:
other: "This question has been asked before and already has an answer."
not_answer:
name:
other: "not an answer"
description:
other: "This was posted as an answer,but it does not attempt to answer the question. It should possibly be an edit,a comment,another question,or deleted altogether."
not_need:
name:
other: "no longer needed"
description:
other: "This comment is outdated,conversational or not relevant to this post."
other:
name:
other: "something else"
description:
other: "This post requires staff attention for another reason not listed above."
question:
close:
duplicate:
name:
other: "spam"
description:
other: "This question has been asked before and already has an answer."
guideline:
name:
other: "a community-specific reason"
description:
other: "This question doesn't meet a community guideline."
multiple:
name:
other: "needs details or clarity"
description:
other: "This question currently includes multiple questions in one. It should focus on one problem only."
other:
name:
other: "something else"
description:
other: "This post requires another reason not listed above."
notification:
action:
update_question:
other: "update question"
answer_the_question:
other: "answer the question"
update_answer:
other: "update answer"
adopt_answer:
other: "adopt answer"
comment_question:
other: "comment question"
comment_answer:
other: "comment answer"
reply_to_you:
other: "reply to you"
mention_you:
other: "mention you"
your_question_is_closed:
other: "your question is closed"
your_question_was_deleted:
other: "your question was deleted"
your_answer_was_deleted:
other: "your answer was deleted"
your_comment_was_deleted:
other: "your comment was deleted"

View File

@ -0,0 +1,25 @@
base:
success:
other: "成功"
unknown:
other: "未知错误"
request_format_error:
other: "请求格式错误"
unauthorized_error:
other: "未登录"
database_error:
other: "数据服务异常"
email:
other: "邮箱"
password:
other: "密码"
username_or_password_wrong_error: &username_or_password_wrong
other: "用户名或密码错误"
error:
user:
username_or_password_wrong: *username_or_password_wrong
admin:
username_or_password_wrong: *username_or_password_wrong

View File

@ -6,6 +6,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/segmentfault/answer/internal/base/conf"
"github.com/segmentfault/answer/internal/cli"
"github.com/segmentfault/pacman"
"github.com/segmentfault/pacman/contrib/conf/viper"
"github.com/segmentfault/pacman/contrib/log/zap"
@ -37,6 +38,19 @@ func init() {
func main() {
flag.Parse()
args := flag.Args()
if len(args) < 1 {
cli.Usage()
os.Exit(0)
return
}
if args[0] == "init" {
cli.InitConfig()
return
}
log.SetLogger(zap.NewLogger(
log.ParseLevel(logLevel), zap.WithName(Name), zap.WithPath(logPath), zap.WithCallerFullPath()))

6
configs/config.go Normal file
View File

@ -0,0 +1,6 @@
package configs
import _ "embed"
//go:embed config.yaml
var Config []byte

View File

@ -1,19 +1,19 @@
server:
http:
addr: ""
addr: 0.0.0.0:80
data:
database:
connection: ""
connection: root:root@tcp(127.0.0.1:3306)/answer
cache:
file_path: ""
file_path: "/tmp/cache/cache.db"
i18n:
bundle_dir: ""
bundle_dir: "/data/i18n"
swaggerui:
show: true
show: false
protocol: http
host: 0
address: ':'
host: 127.0.0.1
address: ':80'
service_config:
secret_key: ""
web_host: ""
upload_path: ""
secret_key: "answer"
web_host: "http://127.0.0.1"
upload_path: "./upfiles"

View File

@ -4,4 +4,6 @@ services:
build:
context: .
image: github.com/segmentfault/answer
volumes:
- ./data:/data
restart: on-failure

6
i18n/i18n.go Normal file
View File

@ -0,0 +1,6 @@
package I18n
import "embed"
//go:embed *.yaml
var I18n embed.FS

89
internal/cli/install.go Normal file
View File

@ -0,0 +1,89 @@
package cli
import (
"bufio"
"fmt"
"os"
"github.com/segmentfault/answer/I18n"
"github.com/segmentfault/answer/configs"
"github.com/segmentfault/answer/pkg/dir"
)
var SuccessMsg = `
answer initialized successfully
`
var HasBeenInitializedMsg = `
Has been initialized.
`
func InitConfig() {
exist, err := PathExists("data/config.yaml")
if err != nil {
fmt.Println(err.Error())
os.Exit(2)
}
if exist {
fmt.Println(HasBeenInitializedMsg)
os.Exit(0)
}
_, err = dir.CreatePathIsNotExist("data")
if err != nil {
fmt.Println(err.Error())
os.Exit(2)
}
WriterFile("data/config.yaml", string(configs.Config))
_, err = dir.CreatePathIsNotExist("data/i18n")
if err != nil {
fmt.Println(err.Error())
os.Exit(2)
}
_, err = dir.CreatePathIsNotExist("data/upfiles")
if err != nil {
fmt.Println(err.Error())
os.Exit(2)
}
i18nList, err := I18n.I18n.ReadDir(".")
if err != nil {
fmt.Println(err.Error())
os.Exit(2)
}
for _, item := range i18nList {
path := fmt.Sprintf("data/i18n/%s", item.Name())
content, err := I18n.I18n.ReadFile(item.Name())
if err != nil {
continue
}
WriterFile(path, string(content))
}
fmt.Println(SuccessMsg)
os.Exit(0)
}
func WriterFile(filePath, content string) error {
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
return err
}
defer file.Close()
if err != nil {
return err
}
write := bufio.NewWriter(file)
write.WriteString(content)
write.Flush()
return nil
}
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}

18
internal/cli/usage.go Normal file
View File

@ -0,0 +1,18 @@
package cli
import "fmt"
var usageDoc = `
answer
USAGE
answer command
COMMANDS
init init answer config
-c config path, eg: -c data/config.yaml
`
func Usage() {
fmt.Println(usageDoc)
}