Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangyuanliu committed Jun 17, 2024
0 parents commit 1baf3fb
Show file tree
Hide file tree
Showing 29 changed files with 1,441 additions and 0 deletions.
26 changes: 26 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
name: 报告问题
about: 使用简练详细的语言描述你遇到的问题
title: ''
labels: bug
assignees: ''

---

**例行检查**

[//]: # (方框内删除已有的空格,填 x 号)
+ [ ] 我已确认目前没有类似 issue
+ [ ] 我已确认我已升级到最新版本
+ [ ] 我已完整查看过项目 README,尤其是常见问题部分
+ [ ] 我理解并愿意跟进此 issue,协助测试和提供反馈
+ [ ] 我理解并认可上述内容,并理解项目维护者精力有限,**不遵循规则的 issue 可能会被无视或直接关闭**

**问题描述**

**复现步骤**

**预期结果**

**相关截图**
如果没有的话,请删除此节。
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
blank_issues_enabled: false
contact_links: ""
21 changes: 21 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: 功能请求
about: 使用简练详细的语言描述希望加入的新功能
title: ''
labels: enhancement
assignees: ''

---

**例行检查**

[//]: # (方框内删除已有的空格,填 x 号)
+ [ ] 我已确认目前没有类似 issue
+ [ ] 我已确认我已升级到最新版本
+ [ ] 我已完整查看过项目 README,已确定现有版本无法满足需求
+ [ ] 我理解并愿意跟进此 issue,协助测试和提供反馈
+ [ ] 我理解并认可上述内容,并理解项目维护者精力有限,**不遵循规则的 issue 可能会被无视或直接关闭**

**功能描述**

**应用场景**
18 changes: 18 additions & 0 deletions .github/workflows/deploy-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Docker Image CI/CD
on:
push:
branches: [ main ]
jobs:
# 构建并上传 Docker镜像
build:
runs-on: ubuntu-latest # 依赖的环境
steps:
- uses: actions/checkout@v2
- name: Build Image
run: |
docker build --platform linux/amd64 -t lumaapi/luma-api .
- name: Login to Registry
run: docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
- name: Push Image
run: |
docker push lumaapi/luma-api
5 changes: 5 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/luma-api.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM golang AS builder

ENV GO111MODULE=on \
GOOS=linux \
GOPROXY=https://goproxy.cn,direct

WORKDIR /build
ADD go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -ldflags "-s -w -extldflags '-static'" -o lumaApi

FROM alpine:latest

RUN apk update \
&& apk upgrade \
&& apk add --no-cache ca-certificates tzdata gcc \
&& update-ca-certificates 2>/dev/null || true

COPY --from=builder /build/lumaApi /

EXPOSE 8000

ENTRYPOINT ["/lumaApi"]
Binary file added README.md
Binary file not shown.
Binary file added README_ZH.md
Binary file not shown.
117 changes: 117 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package main

import (
"fmt"
"github.com/gin-gonic/gin"
"io"
"luma-api/common"
"net/http"
)

var CommonHeaders = map[string]string{
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
"Referer": "https://lumalabs.ai/",
"Origin": "https://lumalabs.ai",
"Accept": "*/*",
}

// @Summary Submit luma generate video task
// @Schemes
// @Description
// @Accept json
// @Produce json
// @Param body body GenRequest true "submit generate video"
// @Success 200 {object} []VideoTask "generate result"
// @Router /luma/generations [post]
func Generations(c *gin.Context) {
header := map[string]string{
"Cookie": common.COOKIE,
}
for k, v := range CommonHeaders {
header[k] = v
}

resp, err := DoRequest("POST", fmt.Sprintf(common.BaseUrl+"/api/photon/v1/generations/"), c.Request.Body, header)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"detail": map[string]any{
"reason": err.Error(),
"code": 1,
},
})
return
}
defer resp.Body.Close()

c.Writer.WriteHeader(resp.StatusCode)
for key, values := range resp.Header {
for _, value := range values {
c.Writer.Header().Add(key, value)
}
}
// 读取响应体
_, err = io.Copy(c.Writer, resp.Body)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"detail": map[string]any{
"reason": err.Error(),
"code": 1,
},
})
return
}
}

// @Summary Submit luma generate video task
// @Schemes
// @Description
// @Accept json
// @Produce json
// @Success 200 {object} []VideoTask "video tasks"
// @Router /luma/generations/{id} [get]
// @Router /luma/generations/ [get]
func Fetch(c *gin.Context) {
action := c.Param("action")

header := map[string]string{
"Cookie": common.COOKIE,
}
for k, v := range CommonHeaders {
header[k] = v
}
url := fmt.Sprintf(common.BaseUrl+"/api/photon/v1/generations%s", action)
if c.Request.URL.RawQuery != "" {
url = fmt.Sprintf("%s?%s", url, c.Request.URL.RawQuery)
}
resp, err := DoRequest("GET", url, nil, header)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"detail": map[string]any{
"reason": err.Error(),
"code": 1,
},
})
return
}
defer resp.Body.Close()

c.Writer.WriteHeader(resp.StatusCode)
for key, values := range resp.Header {
for _, value := range values {
c.Writer.Header().Add(key, value)
}
}
// 读取响应体
_, err = io.Copy(c.Writer, resp.Body)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"detail": map[string]any{
"reason": err.Error(),
"code": 1,
},
})
return
}
return
}
20 changes: 20 additions & 0 deletions common/envs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package common

import (
"os"
"time"
)

var Version = "v0.0.0"
var StartTime = time.Now().Unix() // unit: second

var PProfEnabled = os.Getenv("PPROF") == "true"
var DebugEnabled = os.Getenv("DEBUG") == "true"
var LogDir = GetOrDefaultString("LOG_DIR", "./logs")
var RotateLogs = os.Getenv("ROTATE_LOGS") == "true"

var Port = GetOrDefaultString("PORT", "8000")
var Proxy = GetOrDefaultString("PROXY", "")

var BaseUrl = GetOrDefaultString("BASE_URL", "https://internal-api.virginia.labs.lumalabs.ai")
var COOKIE = GetOrDefaultString("COOKIE", "")
95 changes: 95 additions & 0 deletions common/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package common

import (
"fmt"
"log"
"os"
"path/filepath"
"sync"
"time"

rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

var Logger *zap.SugaredLogger
var LoggerZap *zap.Logger
var setupLogLock sync.Mutex

func SetupLogger() {
if Logger != nil {
return
}
ok := setupLogLock.TryLock()
if !ok {
log.Println("setup log is already working")
return
}
defer func() {
setupLogLock.Unlock()
}()
levelEnabler := zapcore.DebugLevel
syncers := []zapcore.WriteSyncer{zapcore.AddSync(os.Stdout)}

if LogDir != "" {
var err error
LogDir, err = filepath.Abs(LogDir)
if err != nil {
log.Fatal(err)
}
if _, err := os.Stat(LogDir); os.IsNotExist(err) {
err = os.Mkdir(LogDir, 0777)
if err != nil {
log.Fatal(err)
}
}

if RotateLogs {
fd, err := rotatelogs.New(
filepath.Join(LogDir, "%Y%m%d", "%H:%M.log"),
rotatelogs.WithRotationTime(time.Hour),
rotatelogs.WithMaxAge(time.Hour*24*100),
)
if err != nil {
log.Fatal("failed to open rotateLogs")
}
syncers = append(syncers, zapcore.AddSync(fd))
} else {
logPath := filepath.Join(LogDir, fmt.Sprintf("luma2api-%s.log", time.Now().Format("20060102")))
fd, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal("failed to open log file")
}
syncers = append(syncers, zapcore.AddSync(fd))
}
}
enc := zapcore.NewJSONEncoder(zapcore.EncoderConfig{
TimeKey: "_time", // Modified
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
//FunctionKey: zapcore.OmitKey,
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.RFC3339NanoTimeEncoder, // Modified
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
})

loggerCore := zapcore.NewCore(enc,
zapcore.NewMultiWriteSyncer(syncers...),

levelEnabler)
LoggerZap = zap.New(loggerCore,
zap.AddStacktrace(
zap.NewAtomicLevelAt(zapcore.ErrorLevel)),
zap.AddCaller(),
zap.AddCallerSkip(0),
)
Logger = LoggerZap.Sugar()
//gin.DefaultWriter = Logger.Writer()
//gin.DefaultErrorWriter = io.MultiWriter(os.Stderr, logsWriter)
}
Loading

0 comments on commit 1baf3fb

Please sign in to comment.