├── .nvmrc
├── .dockerignore
├── public
├── _redirects
├── favicon.ico
├── favicon.png
└── index.html
├── .browserslistrc
├── src
├── assets
│ ├── 404.png
│ ├── logo.png
│ └── logo.svg
├── plugins
│ └── vuetify.js
├── components
│ ├── Docs
│ │ ├── Minicomment.vue
│ │ ├── Apitable.vue
│ │ └── Reqtable.vue
│ ├── File.vue
│ └── Navbar.vue
├── main.js
├── store
│ └── index.js
├── App.vue
├── api.js
├── router
│ └── index.js
└── views
│ ├── More.vue
│ ├── Login.vue
│ ├── Upload.vue
│ ├── Grid.vue
│ ├── Dashboard.vue
│ └── Docs.vue
├── vue.config.js
├── babel.config.js
├── .env
├── docker-compose.yml
├── .editorconfig
├── .gitignore
├── Dockerfile
├── README.md
├── package.json
└── .eslintrc.js
/.nvmrc:
--------------------------------------------------------------------------------
1 | 12.18.0
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
--------------------------------------------------------------------------------
/public/_redirects:
--------------------------------------------------------------------------------
1 | /* /index.html 200
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waifu-pics/waifu-frontend/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waifu-pics/waifu-frontend/HEAD/public/favicon.png
--------------------------------------------------------------------------------
/src/assets/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waifu-pics/waifu-frontend/HEAD/src/assets/404.png
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waifu-pics/waifu-frontend/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | transpileDependencies: [
3 | 'vuetify',
4 | ],
5 | }
6 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | VUE_APP_API=http://api.waifu.pics/
2 | VUE_APP_CDN=https://i.waifu.pics/
3 | VUE_APP_ROOT_DOMAIN=waifu.pics
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | client:
4 | build: .
5 | ports:
6 | - "8080:8082"
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | trim_trailing_whitespace = true
5 | insert_final_newline = true
6 |
--------------------------------------------------------------------------------
/src/plugins/vuetify.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuetify from 'vuetify/lib'
3 |
4 | Vue.use(Vuetify)
5 |
6 | export default new Vuetify({
7 | })
8 |
--------------------------------------------------------------------------------
/src/components/Docs/Minicomment.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | yarn.lock
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 | .vscode
24 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:alpine AS gobuilder
2 | WORKDIR /app/server
3 | COPY ./server /app/server
4 | RUN cd /app/server && go build -o goapp
5 |
6 | FROM node:lts-alpine AS vuebuilder
7 | WORKDIR /app/client
8 | COPY . .
9 | RUN npm install
10 | RUN npm run build
11 |
12 | FROM alpine
13 | WORKDIR /app
14 | COPY --from=gobuilder /app/server/goapp /app
15 | COPY --from=vuebuilder /app/client/dist /app/dist
16 |
17 | ENTRYPOINT ./goapp
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # waifu.pics
2 |
3 | ## Project setup
4 | ```
5 | yarn install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | yarn serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | yarn build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | yarn lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 | import store from './store'
5 | import vuetify from './plugins/vuetify'
6 | import VueNotification from "@kugatsu/vuenotification"
7 |
8 | Vue.config.productionTip = false
9 |
10 | Vue.use(VueNotification, {
11 | timer: 4,
12 | showLeftIcn: false,
13 | })
14 |
15 | new Vue({
16 | router,
17 | store,
18 | vuetify,
19 | render: h => h(App),
20 | }).$mount('#app')
21 |
--------------------------------------------------------------------------------
/src/components/Docs/Apitable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | URL
6 | Request Type
7 |
8 |
9 |
10 |
11 |
12 | {{type}}
13 |
14 |
15 |
16 |
17 |
18 |
24 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import { api } from '@/api.js'
4 |
5 | Vue.use(Vuex)
6 |
7 | export default new Vuex.Store({
8 | state: {
9 | endpoints: [],
10 | },
11 | mutations: {
12 | endpoints (state) {
13 | api.getEndpoints((res) => {
14 | state.endpoints = res
15 | })
16 | },
17 | },
18 | getters: {
19 | endpoints (state) {
20 | return state.endpoints
21 | },
22 | },
23 | actions: {
24 | },
25 | modules: {
26 | },
27 | })
28 |
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 | Artboard 46
2 |
--------------------------------------------------------------------------------
/src/components/Docs/Reqtable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Field
6 | Data Type
7 | Description
8 |
9 |
10 |
11 |
12 | {{field}}
13 | {{type}}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
26 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
33 |
--------------------------------------------------------------------------------
/src/api.js:
--------------------------------------------------------------------------------
1 | const { default: Axios } = require("axios")
2 |
3 | export const api = {
4 | getEndpoints: (callback) => {
5 | Axios({
6 | method: "get",
7 | url: `${process.env.VUE_APP_API}endpoints`,
8 | }).then((res) => {
9 | callback(res.data)
10 | })
11 | },
12 | checkLoggedIn: () => {
13 | return Axios({
14 | method: "post",
15 | url: `${process.env.VUE_APP_API}admin/login`,
16 | withCredentials: true,
17 | })
18 | },
19 | getOne: (endpoint, nsfw, callback) => {
20 | Axios({
21 | method: "get",
22 | url: `${process.env.VUE_APP_API}${nsfw ? "nsfw" : "sfw"}/${endpoint}`,
23 | }).then((res) => {
24 | callback(res.data)
25 | })
26 | },
27 | }
28 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import More from '@/views/More.vue'
4 | import Grid from '@/views/Grid.vue'
5 | import Docs from '@/views/Docs.vue'
6 | import Login from '@/views/Login.vue'
7 | import Upload from '@/views/Upload.vue'
8 | import Dashboard from '@/views/Dashboard.vue'
9 |
10 | Vue.use(VueRouter)
11 |
12 | const routes = [
13 | {
14 | path: '/',
15 | name: 'Home',
16 | component: Grid,
17 | },
18 | {
19 | path: '/more',
20 | name: 'More',
21 | component: More,
22 | },
23 | {
24 | path: '/docs',
25 | name: 'Docs',
26 | component: Docs,
27 | },
28 | {
29 | path: '/upload',
30 | name: 'Upload',
31 | component: Upload,
32 | },
33 | {
34 | path: '/admin/login',
35 | name: 'Login',
36 | component: Login,
37 | },
38 | {
39 | path: '/admin',
40 | name: 'Admin',
41 | component: Dashboard,
42 | },
43 | {
44 | path: '/:type',
45 | name: 'Grid',
46 | component: Grid,
47 | },
48 | {
49 | path: '/:type/:endpoint',
50 | name: 'Grid',
51 | component: Grid,
52 | },
53 | ]
54 |
55 | const router = new VueRouter({
56 | mode: 'history',
57 | base: process.env.BASE_URL,
58 | routes,
59 | })
60 |
61 | export default router
62 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | <%= htmlWebpackPlugin.options.title %>
19 |
20 |
21 |
22 |
23 |
24 | We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "waifu.pics",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@kugatsu/vuenotification": "^1.1.4",
12 | "atob": "^2.1.2",
13 | "axios": "^0.19.2",
14 | "core-js": "^3.6.5",
15 | "decode-uri-component": "^0.2.0",
16 | "file-type": "^15.0.1",
17 | "filepond": "^4.19.2",
18 | "filepond-plugin-file-metadata": "^1.0.7",
19 | "gsap": "^3.4.2",
20 | "image-type": "^4.1.0",
21 | "source-map-url": "^0.4.0",
22 | "urix": "^0.1.0",
23 | "vue": "^2.6.11",
24 | "vue-filepond": "^6.0.2",
25 | "vue-json-pretty": "^1.6.7",
26 | "vue-notification": "^1.3.20",
27 | "vue-router": "^3.2.0",
28 | "vue-simple-markdown": "^1.1.4",
29 | "vue2-dropzone": "^3.6.0",
30 | "vuejs-noty": "^0.1.3",
31 | "vuetify": "^2.2.11",
32 | "vuex": "^3.4.0"
33 | },
34 | "devDependencies": {
35 | "@vue/cli-plugin-babel": "~4.4.0",
36 | "@vue/cli-plugin-eslint": "~4.4.0",
37 | "@vue/cli-plugin-router": "~4.4.0",
38 | "@vue/cli-plugin-vuex": "~4.4.0",
39 | "@vue/cli-service": "~4.4.0",
40 | "@vue/eslint-config-standard": "^5.1.2",
41 | "babel-eslint": "^10.1.0",
42 | "eslint": "^6.7.2",
43 | "eslint-plugin-import": "^2.20.2",
44 | "eslint-plugin-node": "^11.1.0",
45 | "eslint-plugin-promise": "^4.2.1",
46 | "eslint-plugin-standard": "^4.0.0",
47 | "eslint-plugin-vue": "^6.2.2",
48 | "sass": "^1.26.5",
49 | "sass-loader": "^8.0.2",
50 | "vue-cli-plugin-vuetify": "~2.0.7",
51 | "vue-template-compiler": "^2.6.11",
52 | "vuetify-loader": "^1.3.0"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/views/More.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Pages
7 | Here are all the different pages you can explore.
8 |
9 |
10 |
11 |
12 | SFW
13 |
14 |
15 | {{endpoint}}
16 |
17 |
18 |
19 |
20 | NSFW
21 |
22 |
23 | {{endpoint}}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
50 |
51 |
56 |
--------------------------------------------------------------------------------
/src/views/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Sign in
6 |
login to admin dashboard
7 |
8 |
9 |
10 |
11 |
12 |
13 | Login
14 |
15 |
16 |
17 |
18 |
19 |
31 |
32 |
71 |
--------------------------------------------------------------------------------
/src/components/File.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | mdi-launch
15 |
16 |
17 |
18 | mdi-delete
19 |
20 |
21 |
22 | mdi-check
23 |
24 |
25 |
26 |
27 |
28 |
29 |
66 |
--------------------------------------------------------------------------------
/src/components/Navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{route.icon}}
8 |
9 |
10 | {{route.title}}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {{route.icon}}
19 |
20 |
21 | {{route.title}}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | WAIFU.PICS
31 |
32 |
33 |
34 |
35 |
81 |
--------------------------------------------------------------------------------
/src/views/Upload.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Upload file
8 |
9 |
10 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
72 |
73 |
83 |
84 |
103 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 |
4 | env: {
5 | node: true,
6 | },
7 |
8 | parser: 'vue-eslint-parser',
9 |
10 | parserOptions: {
11 | sourceType: 'module',
12 | parser: 'babel-eslint',
13 | allowImportExportEverywhere: false,
14 | ecmaVersion: 2020,
15 | },
16 |
17 | rules: {
18 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
19 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
20 | 'semi': ['error', 'never'],
21 | "indent": ["error", 2],
22 | 'array-bracket-newline': ['off', 'consistent'],
23 | 'array-element-newline': ['off', {
24 | multiline: true,
25 | minItems: 3,
26 | }],
27 | 'array-bracket-spacing': ['error', 'never'],
28 | 'block-spacing': ['error', 'always'],
29 | 'brace-style': ['error', '1tbs', { allowSingleLine: true }],
30 | camelcase: ['error', {
31 | properties: 'always',
32 | ignoreDestructuring: true,
33 | }],
34 | 'eol-last': ['error', 'always'],
35 | 'function-call-argument-newline': ['off', 'consistent'],
36 | 'func-call-spacing': ['error', 'never'],
37 | 'newline-before-return': 'error',
38 | 'no-mixed-spaces-and-tabs': 'error',
39 | 'no-multi-assign': ['error'],
40 | 'no-multiple-empty-lines': ['error', {
41 | max: 2,
42 | maxBOF: 0,
43 | maxEOF: 0,
44 | }],
45 | 'no-spaced-func': 'error',
46 | 'object-curly-spacing': ['error', 'always'],
47 | 'object-curly-newline': ['error', {
48 | ObjectExpression: {
49 | minProperties: 4,
50 | multiline: true,
51 | consistent: true,
52 | },
53 | ObjectPattern: {
54 | minProperties: 4,
55 | multiline: true,
56 | consistent: true,
57 | },
58 | ImportDeclaration: {
59 | minProperties: 2,
60 | multiline: true,
61 | consistent: true,
62 | },
63 | ExportDeclaration: {
64 | minProperties: 2,
65 | multiline: true,
66 | consistent: true,
67 | },
68 | }],
69 | 'comma-dangle': ['error', {
70 | arrays: 'always-multiline',
71 | objects: 'always-multiline',
72 | imports: 'always-multiline',
73 | exports: 'always-multiline',
74 | functions: 'always-multiline',
75 | }],
76 | 'object-property-newline': ['error', {
77 | allowAllPropertiesOnSameLine: false,
78 | }],
79 | 'space-in-parens': ['error', 'never'],
80 | 'space-infix-ops': 'error',
81 | 'template-tag-spacing': ['error', 'always'],
82 | },
83 |
84 | overrides: [
85 | {
86 | files: ["*.vue"],
87 | extends: [
88 | "plugin:vue/essential",
89 | ],
90 | rules: {
91 | "indent": "off",
92 | "vue/script-indent": ["error", 2, { baseIndent: 0 }],
93 | "vue/html-indent": ["error", 2, { baseIndent: 1 }],
94 | "vue/no-use-v-if-with-v-for": "off",
95 | },
96 | },
97 | ],
98 | }
99 |
--------------------------------------------------------------------------------
/src/views/Grid.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Are you lost?
5 |
Go Home!
6 |
7 |
8 |
9 | mdi-refresh
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
85 |
86 |
134 |
--------------------------------------------------------------------------------
/src/views/Dashboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Search
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | mdi-check
32 |
33 |
34 |
35 | mdi-delete
36 |
37 |
38 |
39 | mdi-select-off
40 |
41 |
42 |
43 |
44 | mdi-logout-variant
45 |
46 |
47 |
48 |
49 |
148 |
149 |
154 |
--------------------------------------------------------------------------------
/src/views/Docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
API Docs
7 |
The open and supported part of the waifu.pics api is incredibly easy to use. You can find more information about how to utilize this in your application below.
8 |
9 |
10 | If you have any issues or questions with the API, please create a Github issue at https://github.com/Waifu-pics/waifu-api
11 |
12 |
13 | Currently we have switched the API url to https://api.waifu.pics from https://waifu.pics/api. While that route does still work, you should switch any existing application to use the newer URL.
14 |
15 |
16 |
17 |
18 |
19 |
Image Categories
20 |
21 |
22 | sfw
23 | nsfw
24 |
25 |
26 |
27 |
28 | {{end}}
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {{end}}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
Get image
49 |
Recieve one image url from your endpoint of choice.
50 |
51 |
52 | {{api}}type /category
53 |
54 |
55 | The type field is the type classification. Valid types are sfw and nsfw .
56 |
57 |
58 |
Response
59 |
Here is an example response for this endpoint
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
Get many images
68 |
Recieve 30 unique images from a specific endpoint or category
69 |
70 |
71 | {{api}}many/type /category
72 |
73 |
74 | The type field is the type classification. Valid types are sfw and nsfw .
75 |
76 |
77 |
Fields
78 |
Fields that can be sent to this endpoint
79 |
80 | A list of URL's to not recieve from this endpoint.
81 |
82 |
83 |
84 |
Response
85 |
Here is an example response for this endpoint
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
120 |
121 |
151 |
--------------------------------------------------------------------------------