Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
VictoriqueMoe committed Mar 12, 2024
0 parents commit 4f9f0a2
Show file tree
Hide file tree
Showing 9 changed files with 416 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto eol=lf
136 changes: 136 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
**/*.iml
.idea/
.idea/**
/build
**build/**
**.idea/**
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module waifuVault-go-api

go 1.21.0
204 changes: 204 additions & 0 deletions pkg/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package main

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"path/filepath"
"waifuVault-go-api/pkg/mod"
)

const baseUrl = "https://waifuvault.moe"

var client = &http.Client{}
var WaifuVault = waifuvalt{}

func main() {
/*url := "http://localhost:3001/"
// don't worry about errors
response, _ := http.Get(url)
var target = mod.WaifuResponse[string]{}
err := json.NewDecoder(response.Body).Decode(&target)
if err != nil {
return
}
fmt.Print(target)*/
/*fileDir, _ := os.Getwd()
fileName := "main.go"
filePath := path.Join(fileDir, "pkg", fileName)
b, err := os.ReadFile(filePath)
if err != nil {
fmt.Print(err)
return
}
fileNames := "main.go"*/

opts := mod.WaifuvaultPutOpts{
Url: "https://victorique.moe/img/slider/Quotes.jpg",
HideFilename: true,
Expires: "1h",
}
file, err := WaifuVault.UploadFile(opts)
if err != nil {
fmt.Print(err)
return
}
fmt.Print(file)
}

type waifuvalt struct {
}

func (re *waifuvalt) UploadFile(options mod.WaifuvaultPutOpts) (*mod.WaifuResponse[string], error) {
if options.File != nil && options.Bytes != nil && options.Url != "" || options.File == nil && options.Bytes == nil && options.Url == "" {
return nil, errors.New("you can only supply buffer, file or url")
}

body := bytes.Buffer{}
var writer *multipart.Writer
if options.File != nil || options.Bytes != nil {

var fileBytes *bytes.Buffer
var w io.Writer
var err error
writer = multipart.NewWriter(&body)
if options.File != nil {
fileBytes = bytes.NewBuffer(nil)
_, err = io.Copy(fileBytes, options.File)
if err != nil {
return nil, err
}
w, err = writer.CreateFormFile("file", filepath.Base(options.File.Name()))
} else {
fileBytes = bytes.NewBuffer(*options.Bytes)
if options.FileName == "" {
return nil, errors.New("FileName must be set if bytes is used")
}
w, err = writer.CreateFormFile("file", options.FileName)
}

if err != nil {
return nil, err
}

if _, err = w.Write(fileBytes.Bytes()); err != nil {
return nil, err
}
err = writer.Close()
if err != nil {
return nil, err
}
} else if options.Url != "" {
bodyUrl := fmt.Sprintf(`{"url": "%s"}`, options.Url)
body = *bytes.NewBuffer([]byte(bodyUrl))
}

uploadUrl := getUrl(map[string]any{
"expires": options.Expires,
"hide_filename": options.HideFilename,
"password": options.Password,
}, nil)

r, err := createRequest(http.MethodPut, uploadUrl, &body, writer)
if err != nil {
return nil, err
}
resp, err := client.Do(r)
if err != nil {
return nil, err
}
return getResponse[string](resp)
}

func createRequest(method, url string, body io.Reader, writer *multipart.Writer) (*http.Request, error) {
r, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
if writer != nil {
r.Header.Add("Content-Type", writer.FormDataContentType())
} else {
r.Header.Set("Content-Type", "application/json")
}
return r, nil
}

func (re *waifuvalt) FileInfo(token string) (*mod.WaifuResponse[string], error) {
return nil, nil
}

func (re *waifuvalt) FileInfoFormatted(token string) (*mod.WaifuResponse[int], error) {
return nil, nil
}

func (re *waifuvalt) DeleteFile(token string) (bool, error) {
return false, nil
}

func (re *waifuvalt) GetFile(options mod.GetFileInfo) ([]byte, error) {
return nil, nil
}

func getUrl(obj map[string]any, path *string) string {
baseRestUrl := fmt.Sprintf("%s/rest", baseUrl)
if path != nil {
baseRestUrl += "/" + *path
}
if obj == nil {
return baseRestUrl
}

params := url.Values{}
for key, val := range obj {
if val == nil || val == "" {
continue
}
params.Add(key, fmt.Sprintf("%v", val))
}

if len(params) > 0 {
return fmt.Sprintf("%s?%s", baseRestUrl, params.Encode())
}

return baseRestUrl
}

func getResponse[T string | int](response *http.Response) (*mod.WaifuResponse[T], error) {
err := checkError(response)
if err != nil {
return nil, err
}
bodyBytes, _ := io.ReadAll(response.Body)
var target = &mod.WaifuResponse[T]{}
err = json.Unmarshal(bodyBytes, target)
if err != nil {
return nil, err
}
return target, nil
}

func checkError(response *http.Response) error {
if response.StatusCode < 200 || response.StatusCode > 299 {
bodyBytes, _ := io.ReadAll(response.Body)
errStr := string(bodyBytes)

var respErrorJson mod.WaifuError
jsonErr := json.Unmarshal(bodyBytes, &respErrorJson)

if jsonErr != nil {
errStr = fmt.Sprintf("Error %d (%s): %s", respErrorJson.Status, respErrorJson.Name, respErrorJson.Message)
}

return errors.New(errStr)
}
return nil
}

func ToPtr[T any](x T) *T {
return &x
}
11 changes: 11 additions & 0 deletions pkg/mod/get_file_opts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package mod

type GetFileInfo struct {
// Password for this file
Password string
// the file token
Token string
// the filename and the file upload epoch. for example, 1710111505084/08.png.
// files with hidden filenames will only contain the epoch with ext. for example, 1710111505084.png
Filename string
}
7 changes: 7 additions & 0 deletions pkg/mod/waifu_error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package mod

type WaifuError struct {
Name string // The name of the HTTP status. e.g: Bad Request
Message string // the message or reason why the request failed
Status int // the http status returned
}
15 changes: 15 additions & 0 deletions pkg/mod/waifu_response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package mod

// WaifuResponse is the response from the api for files and uploads
type WaifuResponse[T string | int] struct {
// Token for the uploaded file
Token string `json:"token"`
// URL to the uploaded file
URL string `json:"url"`
// Protected is if this file is protected-protected/encrypted
Protected bool `json:"protected"`
// RetentionPeriod is a string or a number that represents
// when the file will expire, if called with `format` true, then
// this will be a string like "332 days 7 hours 18 minutes 8 seconds"
RetentionPeriod T `json:"retentionPeriod"`
}
9 changes: 9 additions & 0 deletions pkg/mod/waifu_vault.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package mod

type Waifuvalt interface {
UploadFile(options WaifuvaultPutOpts) (*WaifuResponse[string], error)
FileInfo(token string) (*WaifuResponse[string], error)
FileInfoFormatted(token string) (*WaifuResponse[int], error)
DeleteFile(token string) (bool, error)
GetFile(options GetFileInfo) ([]byte, error)
}
Loading

0 comments on commit 4f9f0a2

Please sign in to comment.