Spaces:
Runtime error
Runtime error
imperialwool
commited on
Commit
•
66ca64a
1
Parent(s):
fd57bb9
Upload 28 files
Browse files- app.py +81 -0
- routes/__init__.py +4 -0
- routes/helpers.py +86 -0
- routes/osuApi/__init__.py +4 -0
- routes/osuApi/findSong.py +35 -0
- routes/osuApi/getBeatmap.py +3 -0
- routes/osuApi/getFull.py +59 -0
- routes/osuApi/getPreview.py +38 -0
- routes/witaiApi/__init__.py +1 -0
- routes/witaiApi/recognizeVoice.py +44 -0
- routes/ytApi/__init__.py +3 -0
- routes/ytApi/get.py +50 -0
- routes/ytApi/getFull.py +26 -0
- routes/ytApi/getPreview.py +33 -0
- routes/ytApi/search.py +22 -0
- static/api.yaml +193 -0
- static/favicon.ico +0 -0
- static/full/.ogg +0 -0
- static/template.yaml +652 -0
- templates/4a1504d326b35eaad3b9d4f48b5119a6/403.html +1 -0
- templates/4a1504d326b35eaad3b9d4f48b5119a6/404.html +1 -0
- templates/4a1504d326b35eaad3b9d4f48b5119a6/429.html +1 -0
- templates/4a1504d326b35eaad3b9d4f48b5119a6/502.html +1 -0
- templates/badgateway.html +1 -0
- templates/forbidden.html +1 -0
- templates/index.html +25 -0
- templates/notfound.html +1 -0
- templates/ratelimit.html +1 -0
app.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from flask import *
|
3 |
+
from flask_limiter import Limiter
|
4 |
+
from flask_limiter.util import get_remote_address
|
5 |
+
|
6 |
+
from routes import *
|
7 |
+
|
8 |
+
app = Flask(__name__)
|
9 |
+
app.config['JSON_AS_ASCII'] = False
|
10 |
+
limiter = Limiter(app, default_limits=["5/minute"], key_func=get_remote_address, storage_uri="memory://",)
|
11 |
+
|
12 |
+
#limiter
|
13 |
+
@limiter.request_filter
|
14 |
+
def ip_whitelist():
|
15 |
+
try:
|
16 |
+
if request.method == 'POST': signature = request.form['signature']
|
17 |
+
else: signature = request.args['signature']
|
18 |
+
return helpers.checkSignature(signature)
|
19 |
+
except: return False
|
20 |
+
#error pages
|
21 |
+
@app.errorhandler(429)
|
22 |
+
def ratelimit_handler(e): return render_template('ratelimit.html')
|
23 |
+
@app.errorhandler(403)
|
24 |
+
def forbidden_handler(e): return render_template('forbidden.html')
|
25 |
+
@app.errorhandler(404)
|
26 |
+
def ratelimit_handler(e): return render_template('notfound.html')
|
27 |
+
|
28 |
+
# site routes
|
29 |
+
@app.route('/')
|
30 |
+
@limiter.exempt
|
31 |
+
def index(): return render_template('index.html')
|
32 |
+
|
33 |
+
#empty routes
|
34 |
+
@app.route('/yt/api/v1', methods=['GET', 'POST'])
|
35 |
+
@app.route('/recognize/api/v1', methods=['GET', 'POST'])
|
36 |
+
@app.route('/osu/api/v1', methods=['GET', 'POST'])
|
37 |
+
def emptyPath(): return {}
|
38 |
+
|
39 |
+
@app.route('/yt/api/v1/<path:path>', methods=['GET', 'POST'])
|
40 |
+
@app.route('/recognize/api/v1/<path:path>', methods=['GET', 'POST'])
|
41 |
+
@app.route('/osu/api/v1/<path:path>', methods=['GET', 'POST'])
|
42 |
+
def emptyApiWA(path): return {"status": "error", "error_code": 100, "error_details": "No method like that found"}
|
43 |
+
|
44 |
+
#for dns-query
|
45 |
+
@app.route('/dns-query', methods=['GET', 'POST'])
|
46 |
+
@limiter.exempt
|
47 |
+
def rerouteto(): return make_response("Wrong port! Use 334 port for dns-query.", 400)
|
48 |
+
|
49 |
+
#icon
|
50 |
+
@app.route('/favicon.ico')
|
51 |
+
@limiter.exempt
|
52 |
+
def favicon(): return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico', mimetype='image/vnd.microsoft.icon')
|
53 |
+
|
54 |
+
###############
|
55 |
+
#RECOGNIZE API
|
56 |
+
@app.route('/recognize/api/v1/voice', methods=['GET', 'POST'])
|
57 |
+
def recognizeVoice(): return witaiApi.recognizeVoice(request)
|
58 |
+
|
59 |
+
###############
|
60 |
+
#YT SOUND API
|
61 |
+
@app.route('/yt/api/v1/search', methods=['GET', 'POST'])
|
62 |
+
def search(): return ytApi.search(request)
|
63 |
+
@app.route('/yt/api/v1/get-full', methods=['GET', 'POST'])
|
64 |
+
def getFull(): return ytApi.getFull(request)
|
65 |
+
@app.route('/yt/api/v1/get-preview', methods=['GET', 'POST'])
|
66 |
+
def getPreview(): return ytApi.getPreview(request)
|
67 |
+
|
68 |
+
###############
|
69 |
+
#OSU API
|
70 |
+
@app.route('/osu/api/v1/find-song', methods=['GET', 'POST'])
|
71 |
+
def findSong(): return osuApi.findSong(request)
|
72 |
+
@app.route('/osu/api/v1/get-beatmap', methods=['GET', 'POST'])
|
73 |
+
def getBeatmap(): return osuApi.getBeatmap(request)
|
74 |
+
@app.route('/osu/api/v1/get-preview', methods=['GET', 'POST'])
|
75 |
+
def getBMPreview(): return osuApi.getPreview(request)
|
76 |
+
@app.route('/osu/api/v1/get-full', methods=['GET', 'POST'])
|
77 |
+
def getBMFull(): return osuApi.getFull(request)
|
78 |
+
|
79 |
+
if __name__ == "__main__":
|
80 |
+
app.run(host="::", port=443, debug=True, ssl_context=('/root/cert.pem', '/root/key.pem'))
|
81 |
+
|
routes/__init__.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from .helpers import *
|
2 |
+
from .witaiApi import *
|
3 |
+
from .ytApi import *
|
4 |
+
from .osuApi import *
|
routes/helpers.py
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import random
|
3 |
+
import string
|
4 |
+
import requests
|
5 |
+
|
6 |
+
# Deleting audio
|
7 |
+
def deleteAudio(path: str, waitInSeconds: int = 0):
|
8 |
+
os.system("rm /home/ubuntu/api/static/{}".format(path))
|
9 |
+
|
10 |
+
# Signatures!!! Wow!!!
|
11 |
+
def checkSignature(signature: str):
|
12 |
+
signatureList = [
|
13 |
+
"008610493EAF05823A1C409C551511BA22C9139B97E78C7AC32E36A5992D5FFB2F846B312EE24ED8FA0AEE83700498F341A1AA46E148F05725867D7C51459A1F",
|
14 |
+
"B2A61FBD11D39A611951D803045B7FCE8A76360099127BA9DD1F6B0B691CFF3320D11916AB5297B811149C3BC65D97777D1DE588249863A7C0E877AD13235C99"
|
15 |
+
]
|
16 |
+
return signature in signatureList
|
17 |
+
|
18 |
+
# Hook for yt-dlp
|
19 |
+
def thisIsHook(d):
|
20 |
+
if d['total_bytes'] > 52428800:
|
21 |
+
print("\nFILE IS BIG, ABORT!!!\n")
|
22 |
+
raise Exception(f"Too long file (recieved {d['total_bytes']/1048576}MB, max is 50MB)")
|
23 |
+
|
24 |
+
# Recognizing things
|
25 |
+
def req(access_token, meth, path, params, **kwargs):
|
26 |
+
full_url = "https://api.wit.ai" + path
|
27 |
+
headers = {
|
28 |
+
"authorization": "Bearer " + access_token,
|
29 |
+
"accept": "application/vnd.wit." + "20221114" + "+json",
|
30 |
+
}
|
31 |
+
headers.update(kwargs.pop("headers", {}))
|
32 |
+
rsp = requests.request(meth, full_url, headers=headers, params=params, **kwargs)
|
33 |
+
if rsp.status_code > 200:
|
34 |
+
raise Exception(
|
35 |
+
str(rsp.status_code)
|
36 |
+
+ " ("
|
37 |
+
+ rsp.reason
|
38 |
+
+ ")"
|
39 |
+
)
|
40 |
+
try: r = rsp.json()
|
41 |
+
except: r = rsp.text
|
42 |
+
if "error" in r:
|
43 |
+
raise Exception(json["error"])
|
44 |
+
|
45 |
+
return r
|
46 |
+
def dictation(access_token, audio_file, headers=None, verbose=None):
|
47 |
+
params = {}
|
48 |
+
headers = headers or {}
|
49 |
+
if verbose:
|
50 |
+
params["verbose"] = True
|
51 |
+
resp = req(
|
52 |
+
access_token,
|
53 |
+
"POST",
|
54 |
+
"/dictation",
|
55 |
+
params,
|
56 |
+
data=audio_file,
|
57 |
+
headers=headers,
|
58 |
+
)
|
59 |
+
return resp
|
60 |
+
def clean(text):
|
61 |
+
if text not in ['', None]:
|
62 |
+
return text.replace('?', '').replace('!', '').replace(';', '').replace('.', '').replace(',', '')
|
63 |
+
def delivering(text):
|
64 |
+
result = []
|
65 |
+
temp = None
|
66 |
+
toPush = None
|
67 |
+
tempLength = 0
|
68 |
+
for dirtLine in text.split('\n'):
|
69 |
+
if '"text"' in dirtLine:
|
70 |
+
line = dirtLine[11:-1]
|
71 |
+
if temp == None: temp = line
|
72 |
+
else:
|
73 |
+
if temp in line: toPush = line
|
74 |
+
else:
|
75 |
+
temp = line
|
76 |
+
result.append(toPush)
|
77 |
+
return ' '.join(result)
|
78 |
+
def devRaw(text):
|
79 |
+
result = []
|
80 |
+
for line in text.split('\n'): #line[11:-1]
|
81 |
+
if '"text"' in line:
|
82 |
+
result.append(line[11:-1])
|
83 |
+
return result
|
84 |
+
|
85 |
+
def randString(len: int = 16):
|
86 |
+
return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(len))
|
routes/osuApi/__init__.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from .findSong import *
|
2 |
+
from .getBeatmap import *
|
3 |
+
from .getPreview import *
|
4 |
+
from .getFull import *
|
routes/osuApi/findSong.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from .. import helpers
|
3 |
+
from requests import get
|
4 |
+
from random import randint as rand
|
5 |
+
def findSong(request):
|
6 |
+
try:
|
7 |
+
if request.method == 'POST': signature = request.form['signature']
|
8 |
+
else: signature = request.args['signature']
|
9 |
+
except: return {"status": "error", "details": { "error_code": 103, "error_details": "No signature" }}
|
10 |
+
if not helpers.checkSignature(signature): return {"status": "error", "details": { "error_code": 105, "error_details": "Invalid signature" }}
|
11 |
+
|
12 |
+
try:
|
13 |
+
if request.method == 'POST': query = request.form['query']
|
14 |
+
else: query = request.args['query']
|
15 |
+
if query.strip() in ['', None]: raise Exception()
|
16 |
+
except: return {"status": "error", "details": { "error_code": 133, "error_details": "No query" }}
|
17 |
+
|
18 |
+
tryment = get("https://api.chimu.moe/v1/search", params={"query": query})
|
19 |
+
if int(tryment.status_code) not in [404, 403]:
|
20 |
+
res = []
|
21 |
+
counter = 0
|
22 |
+
for chunk in tryment.json()['data']:
|
23 |
+
res.append({
|
24 |
+
"beatmapId": chunk['SetId'],
|
25 |
+
"artist": chunk['Artist'],
|
26 |
+
"title": chunk['Title'],
|
27 |
+
"creator": chunk['Creator'],
|
28 |
+
"source": chunk['Source'],
|
29 |
+
"tags": chunk['Tags']
|
30 |
+
})
|
31 |
+
counter += 1
|
32 |
+
if counter >= rand(3,7): break
|
33 |
+
return {"status": "pass", "details": {"code": int(tryment.status_code), "result": res}}
|
34 |
+
else:
|
35 |
+
return {"status": "error", "details": {"code": int(tryment.status_code), "answer": tryment.text}}
|
routes/osuApi/getBeatmap.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from .. import helpers
|
2 |
+
def getBeatmap(request):
|
3 |
+
return {"status": "error", "details": {"code": -1, "answer": "Under construction"}}
|
routes/osuApi/getFull.py
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import ffmpeg
|
3 |
+
from .. import helpers
|
4 |
+
from .findSong import *
|
5 |
+
from requests import get
|
6 |
+
from random import randint as rand
|
7 |
+
def getFull(request):
|
8 |
+
try:
|
9 |
+
if request.method == 'POST': signature = request.form['signature']
|
10 |
+
else: signature = request.args['signature']
|
11 |
+
except: return {"status": "error", "details": { "error_code": 103, "error_details": "No signature" }}
|
12 |
+
if not helpers.checkSignature(signature): return {"status": "error", "details": { "error_code": 105, "error_details": "Invalid signature" }}
|
13 |
+
|
14 |
+
try:
|
15 |
+
if request.method == 'POST': beatmapId = request.form['beatmapId']
|
16 |
+
else: beatmapId = request.args['beatmapId']
|
17 |
+
if beatmapId.strip() in ['', None]:
|
18 |
+
raise Exception()
|
19 |
+
except: beatmapId = None
|
20 |
+
|
21 |
+
try:
|
22 |
+
if request.method == 'POST': query = request.form['query']
|
23 |
+
else: query = request.args['query']
|
24 |
+
if query.strip() in ['', None]:
|
25 |
+
raise Exception()
|
26 |
+
except:
|
27 |
+
if beatmapId == None: return {"status": "error", "details": { "error_code": 133, "error_details": "No details for finding preview" }}
|
28 |
+
else: query = None
|
29 |
+
|
30 |
+
if beatmapId != None:
|
31 |
+
if os.path.exists(f"/home/ubuntu/api/static/full/{beatmapId}.ogg"):
|
32 |
+
return {"status": "pass", "details": {"code": 200, "result": "https://funapi.dnszilla.bar/static/full/{}.ogg".format(beatmapId)}}
|
33 |
+
tryment = get("https://kitsu.moe/api/audio/{}".format(beatmapId), allow_redirects=True)
|
34 |
+
if int(tryment.status_code) not in [404, 403, 429]:
|
35 |
+
open(f"/home/ubuntu/api/static/temp/{beatmapId}.mp3", "wb").write(tryment.content)
|
36 |
+
audio_input = ffmpeg.input(f"/home/ubuntu/api/static/temp/{beatmapId}.mp3")
|
37 |
+
audio_output = ffmpeg.output(audio_input, "/home/ubuntu/api/static/full/{}.ogg".format(beatmapId), audio_bitrate="96K")
|
38 |
+
ffmpeg.run(audio_output)
|
39 |
+
helpers.deleteAudio("temp/{}.ogg".format(beatmapId))
|
40 |
+
return {"status": "pass", "details": {"code": int(tryment.status_code), "result": "https://funapi.dnszilla.bar/static/full/{}.ogg".format(beatmapId)}}
|
41 |
+
else:
|
42 |
+
return {"status": "error", "details": {"code": int(tryment.status_code), "answer": tryment.text}}
|
43 |
+
if query != None:
|
44 |
+
fffff = findSong(request)
|
45 |
+
if fffff['status'] == "error": return fffff
|
46 |
+
beatmapId = fffff['details']['result'][rand(0,len(fffff['details']['result']))]['beatmapId']
|
47 |
+
if os.path.exists(f"/home/ubuntu/api/static/full/{beatmapId}.ogg"):
|
48 |
+
return {"status": "pass", "details": {"code": 200, "result": "https://funapi.dnszilla.bar/static/full/{}.ogg".format(beatmapId)}}
|
49 |
+
tryment = get("https://kitsu.moe/api/audio/{}".format(beatmapId), allow_redirects=True)
|
50 |
+
if int(tryment.status_code) not in [404, 403, 429]:
|
51 |
+
open(f"/home/ubuntu/api/static/temp/{beatmapId}.mp3", "wb").write(tryment.content)
|
52 |
+
audio_input = ffmpeg.input(f"/home/ubuntu/api/static/temp/{beatmapId}.mp3")
|
53 |
+
audio_output = ffmpeg.output(audio_input, "/home/ubuntu/api/static/full/{}.ogg".format(beatmapId), audio_bitrate="96K")
|
54 |
+
ffmpeg.run(audio_output)
|
55 |
+
helpers.deleteAudio("temp/{}.ogg".format(beatmapId))
|
56 |
+
return {"status": "pass", "details": {"code": int(tryment.status_code), "result": "https://funapi.dnszilla.bar/static/full/{}.ogg".format(beatmapId)}}
|
57 |
+
else:
|
58 |
+
return {"status": "error", "details": {"code": int(tryment.status_code), "answer": tryment.text}}
|
59 |
+
return {}
|
routes/osuApi/getPreview.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from .. import helpers
|
2 |
+
from .findSong import *
|
3 |
+
from requests import get
|
4 |
+
from random import randint as rand
|
5 |
+
def getPreview(request):
|
6 |
+
try:
|
7 |
+
if request.method == 'POST': signature = request.form['signature']
|
8 |
+
else: signature = request.args['signature']
|
9 |
+
except: return {"status": "error", "details": { "error_code": 103, "error_details": "No signature" }}
|
10 |
+
if not helpers.checkSignature(signature): return {"status": "error", "details": { "error_code": 105, "error_details": "Invalid signature" }}
|
11 |
+
|
12 |
+
try:
|
13 |
+
if request.method == 'POST': beatmapId = request.form['beatmapId']
|
14 |
+
else: beatmapId = request.args['beatmapId']
|
15 |
+
if beatmapId.strip() in ['', None]:
|
16 |
+
raise Exception()
|
17 |
+
except: beatmapId = None
|
18 |
+
|
19 |
+
try:
|
20 |
+
if request.method == 'POST': query = request.form['query']
|
21 |
+
else: query = request.args['query']
|
22 |
+
if query.strip() in ['', None]:
|
23 |
+
raise Exception()
|
24 |
+
except:
|
25 |
+
if beatmapId == None: return {"status": "error", "details": { "error_code": 133, "error_details": "No details for finding preview" }}
|
26 |
+
else: query = None
|
27 |
+
|
28 |
+
if beatmapId != None:
|
29 |
+
tryment = get("https://b.ppy.sh/preview/{}.mp3".format(beatmapId))
|
30 |
+
if int(tryment.status_code) not in [404, 403]:
|
31 |
+
return {"status": "pass", "details": {"code": int(tryment.status_code), "result": "https://b.ppy.sh/preview/{}.mp3".format(beatmapId)}}
|
32 |
+
else:
|
33 |
+
return {"status": "error", "details": {"code": int(tryment.status_code), "answer": tryment.text}}
|
34 |
+
if query != None:
|
35 |
+
fffff = findSong(request)
|
36 |
+
if fffff['status'] == "error": return fffff
|
37 |
+
return {"status": "pass", "details": {"code": fffff['details']['code'], "result": "https://b.ppy.sh/preview/{}.mp3".format(fffff['details']['result'][rand(0,len(fffff['details']['result']))]['beatmapId'])}}
|
38 |
+
return {}
|
routes/witaiApi/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
from .recognizeVoice import *
|
routes/witaiApi/recognizeVoice.py
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import wget
|
2 |
+
import random
|
3 |
+
import string
|
4 |
+
from .. import helpers
|
5 |
+
|
6 |
+
def recognizeVoice(request):
|
7 |
+
try:
|
8 |
+
if request.method == 'POST': url = request.form['url']
|
9 |
+
else: url = request.args['url']
|
10 |
+
if url.strip() in ['', None]: raise Exception()
|
11 |
+
except: return {"status": "error", "details": { "error_code": 101, "error_details": "No link provided" }}
|
12 |
+
try:
|
13 |
+
if request.method == 'POST': signature = request.form['signature']
|
14 |
+
else: signature = request.args['signature']
|
15 |
+
except: return {"status": "error", "details": { "error_code": 103, "error_details": "No signature" }}
|
16 |
+
try:
|
17 |
+
if request.method == 'POST': extendInfo = request.form['extendInfo']
|
18 |
+
else: extendInfo = request.args['extendInfo']
|
19 |
+
if extendInfo in ['true','1',1,'yes','y']: extendInfo = True
|
20 |
+
else: extendInfo = False
|
21 |
+
except: extendInfo = False
|
22 |
+
|
23 |
+
fileId = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(16))
|
24 |
+
fileExt = url[url.rfind('.'):url.rfind('.')+4]
|
25 |
+
if fileExt == ".wav": fileHeader = {'Content-Type': 'audio/wav'}
|
26 |
+
elif fileExt == ".mp3": fileHeader = {'Content-Type': 'audio/mpeg3'}
|
27 |
+
elif fileExt == ".ogg": fileHeader = {'Content-Type': 'audio/ogg'}
|
28 |
+
else: return {"status": "error", "details": { "error_code": 111, "error_details": "Wrong file format (only ogg, wav, mp3)" }}
|
29 |
+
wget.download(url, f"/home/ubuntu/api/static/temp/{fileId}{fileExt}")
|
30 |
+
noEx = True
|
31 |
+
with open(f"/home/ubuntu/api/static/temp/{fileId}{fileExt}", 'rb') as f:
|
32 |
+
try: resp = helpers.dictation("ANR3UUMGUHZJFF366EY3YM3FS54QDJPF", f, {'Content-Type': 'audio/mpeg3'})
|
33 |
+
except Exception as e:
|
34 |
+
noEx = False
|
35 |
+
resp = e
|
36 |
+
helpers.deleteAudio(f"temp/{fileId}{fileExt}")
|
37 |
+
try:
|
38 |
+
if resp['text'] == "": return {"status": "ok", "result": "", "details": ""}
|
39 |
+
except: pass
|
40 |
+
if noEx:
|
41 |
+
|
42 |
+
if extendInfo: return {"status": "ok", "result": helpers.delivering(resp), "details": str(helpers.devRaw(resp))}
|
43 |
+
else: return {"status": "ok", "result": helpers.delivering(resp)}
|
44 |
+
else: return {"status": "error", "details": { "error_code": 123, "error_details": resp }}
|
routes/ytApi/__init__.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from .getFull import *
|
2 |
+
from .getPreview import *
|
3 |
+
from .search import *
|
routes/ytApi/get.py
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import yt_dlp
|
3 |
+
from .. import helpers
|
4 |
+
|
5 |
+
def get(request, check = "huh"):
|
6 |
+
try:
|
7 |
+
if request.method == 'POST': signature = request.form['signature']
|
8 |
+
else: signature = request.args['signature']
|
9 |
+
except: return {"status": "error", "details": { "error_code": 103, "error_details": "No signature" }}
|
10 |
+
if not helpers.checkSignature(signature): return {"status": "error", "details": { "error_code": 105, "error_details": "Invalid signature" }}
|
11 |
+
|
12 |
+
try:
|
13 |
+
if request.method == 'POST': url = request.form['url']
|
14 |
+
else: url = request.args['url']
|
15 |
+
if url.strip() in ['', None]:
|
16 |
+
raise Exception()
|
17 |
+
except: return {"status": "error", "details": { "error_code": 101, "error_details": "No link provided" }}
|
18 |
+
|
19 |
+
try:
|
20 |
+
if request.method == 'POST': bitrate = str(request.form['bitrate'])
|
21 |
+
else: bitrate = str(request.args['bitrate'])
|
22 |
+
except: bitrate = "64k"
|
23 |
+
try:
|
24 |
+
if request.method == 'POST': quality = request.form['quality']
|
25 |
+
else: quality = request.args['quality']
|
26 |
+
if quality.lower() not in ['best', 'worst']: raise Exception()
|
27 |
+
except: quality = 'worst'
|
28 |
+
|
29 |
+
urlcode = None
|
30 |
+
try: urlcode = url.partition('?v=')[2]
|
31 |
+
except: urlcode = helpers.randString()
|
32 |
+
if urlcode in ['', None]: urlcode = helpers.randString()
|
33 |
+
|
34 |
+
if os.path.exists("/home/ubuntu/api/static/{}/{}.ogg".format(check, urlcode)):
|
35 |
+
return {"status": "pass", 'done-or-not': True, 'ytdlp-code': 0, 'urlcode': urlcode, "path": "/home/ubuntu/api/static/{}/{}.ogg".format(check, urlcode), "quality": quality, "bitrate": bitrate}
|
36 |
+
|
37 |
+
if os.path.exists("/home/ubuntu/api/static/temp/{}.ogg".format(urlcode)):
|
38 |
+
return {"status": "pass", 'done-or-not': False, 'ytdlp-code': 0, 'urlcode': urlcode, "path": "/home/ubuntu/api/static/temp/{}.ogg".format(urlcode), "quality": quality, "bitrate": bitrate}
|
39 |
+
|
40 |
+
ydl_opts = {
|
41 |
+
'format': f'ogg/{quality}audio/{quality}',
|
42 |
+
'outtmpl': "/home/ubuntu/api/static/temp/{}.ogg".format(urlcode),
|
43 |
+
'progress_hooks': [helpers.thisIsHook],
|
44 |
+
}
|
45 |
+
|
46 |
+
try:
|
47 |
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
48 |
+
error_code = ydl.download(url)
|
49 |
+
except Exception as e: return {"status": "error", "details": {"error_code": 102, "error_details": str(e)}}
|
50 |
+
return {"status": "pass", 'done-or-not': False, 'ytdlp-code': error_code, 'urlcode': urlcode, "path": "/home/ubuntu/api/static/temp/{}.ogg".format(urlcode), "quality": quality, "bitrate": bitrate}
|
routes/ytApi/getFull.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import ffmpeg
|
2 |
+
from .get import *
|
3 |
+
from .. import helpers
|
4 |
+
|
5 |
+
def getFull(request):
|
6 |
+
answer = get(request, "full")
|
7 |
+
try:
|
8 |
+
if answer['error']: return answer
|
9 |
+
except KeyError: pass
|
10 |
+
except Exception as e: return {"status": "error", "details": { "error_code": 123, "error_details": e }}
|
11 |
+
urlcode = answer['urlcode']
|
12 |
+
bitrate = answer['bitrate']
|
13 |
+
quality = answer['quality']
|
14 |
+
error_code = answer['ytdlp-code']
|
15 |
+
|
16 |
+
if answer['done-or-not']:
|
17 |
+
return {"status": "pass", "details": {"code": error_code, "name":"{}.ogg".format(urlcode), "result": "http://funapi.dnszilla.bar/static/full/{}.ogg".format(urlcode)}}
|
18 |
+
|
19 |
+
try:
|
20 |
+
audio_input = ffmpeg.input(answer['path'])
|
21 |
+
audio_output = ffmpeg.output(audio_input.audio, "/home/ubuntu/api/static/full/{}.ogg".format(urlcode), audio_bitrate=bitrate)
|
22 |
+
ffmpeg.run(audio_output)
|
23 |
+
helpers.deleteAudio("temp/{}.ogg".format(urlcode))
|
24 |
+
except Exception as e: return {"status": "error", "details": {"error_code": 102, "error_details": str(e), "result": "http://funapi.dnszilla.bar/static/temp/{}.ogg".format(urlcode)}}
|
25 |
+
return {"status": "pass", "details": {"code": error_code, "name":"{}.ogg".format(urlcode), "result": "http://funapi.dnszilla.bar/static/full/{}.ogg".format(urlcode)}}
|
26 |
+
|
routes/ytApi/getPreview.py
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import ffmpeg
|
2 |
+
from .get import *
|
3 |
+
from .. import helpers
|
4 |
+
|
5 |
+
def getPreview(request):
|
6 |
+
answer = get(request, "previews")
|
7 |
+
try:
|
8 |
+
if answer['error']: return answer
|
9 |
+
except KeyError: pass
|
10 |
+
except Exception as e: return {"status": "error", "details": { "error_code": 123, "error_details": e }}
|
11 |
+
urlcode = answer['urlcode']
|
12 |
+
bitrate = answer['bitrate']
|
13 |
+
quality = answer['quality']
|
14 |
+
error_code = answer['ytdlp-code']
|
15 |
+
|
16 |
+
try:
|
17 |
+
if request.method == 'POST': duration = request.form['duration']
|
18 |
+
else: duration = request.args['duration']
|
19 |
+
if duration > 60: duration = 60
|
20 |
+
except: duration = 30
|
21 |
+
|
22 |
+
if answer['done-or-not']:
|
23 |
+
return {"status": "pass", "details": {"code": error_code, "name":"{}.ogg".format(urlcode), "result": "http://funapi.dnszilla.bar/static/previews/{}.ogg".format(urlcode)}}
|
24 |
+
|
25 |
+
try:
|
26 |
+
audio_input = ffmpeg.input(answer['path'])
|
27 |
+
audio_cut = audio_input.audio.filter('atrim', duration=duration)
|
28 |
+
audio_output = ffmpeg.output(audio_cut, "/home/ubuntu/api/static/previews/{}.ogg".format(urlcode), audio_bitrate=bitrate)
|
29 |
+
ffmpeg.run(audio_output)
|
30 |
+
helpers.deleteAudio("temp/{}.ogg".format(urlcode))
|
31 |
+
except Exception as e: return {"status": "error", "details": {"error_code": 102, "error_details": str(e), "result": "http://funapi.dnszilla.bar/static/temp/{}.ogg".format(urlcode)}}
|
32 |
+
return {"status": "pass", "details": {"code": error_code, "name":"{}.ogg".format(urlcode), "result": "http://funapi.dnszilla.bar/static/previews/{}.ogg".format(urlcode)}}
|
33 |
+
|
routes/ytApi/search.py
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import urllib
|
2 |
+
import re
|
3 |
+
from .. import helpers
|
4 |
+
|
5 |
+
def search(request):
|
6 |
+
try:
|
7 |
+
if request.method == 'POST': searchQuery = request.form['query']
|
8 |
+
else: searchQuery = request.args['query']
|
9 |
+
if searchQuery.strip() in ['', None]:
|
10 |
+
raise Exception()
|
11 |
+
except: searchQuery = "rickroll"
|
12 |
+
try:
|
13 |
+
if request.method == 'POST': signature = request.form['signature']
|
14 |
+
else: signature = request.args['signature']
|
15 |
+
except: return {"status": "error", "details": { "error_code": 103, "error_details": "No signature" }}
|
16 |
+
if not helpers.checkSignature(signature): return {"status": "error", "details": { "error_code": 105, "error_details": " signature" }}
|
17 |
+
html = urllib.request.urlopen("https://www.youtube.com/results?search_query={}".format(urllib.parse.quote_plus(searchQuery)))
|
18 |
+
videoList = re.findall(r"watch\?v=(\S{11})", html.read().decode())
|
19 |
+
videoIds = dict()
|
20 |
+
for i in range(len(videoList)):
|
21 |
+
videoIds.update({i: videoList[i]})
|
22 |
+
return {"status": "pass", "query": searchQuery, "videoIds": videoIds}
|
static/api.yaml
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
openapi: 3.0.0
|
2 |
+
info:
|
3 |
+
title: DNSZilla's FunAPI
|
4 |
+
description: Collection of APIs for bots or just fun by @imperialwool. Thx DNSZilla for host!
|
5 |
+
version: 0.1.103
|
6 |
+
servers:
|
7 |
+
- url: 'https://funapi.dnszilla.bar/'
|
8 |
+
description: Main API.
|
9 |
+
paths:
|
10 |
+
/recognize/api/v1/voice:
|
11 |
+
get:
|
12 |
+
tags:
|
13 |
+
- Recognize API
|
14 |
+
parameters:
|
15 |
+
- name: 'url'
|
16 |
+
description: URL-link to voice message. Should be mp3, ogg or wav.
|
17 |
+
in: 'query'
|
18 |
+
schema:
|
19 |
+
type: 'string'
|
20 |
+
example: https://cdn-102.anonfiles.com/q8v0o5O5y8/3d62dac1-1671893935/j4893hg894g4.mp3
|
21 |
+
- name: 'extendInfo'
|
22 |
+
description: Provide additional information or not.
|
23 |
+
in: 'query'
|
24 |
+
schema:
|
25 |
+
type: 'string'
|
26 |
+
default: False
|
27 |
+
example: False
|
28 |
+
- name: 'signature'
|
29 |
+
description: Special access key.
|
30 |
+
in: 'query'
|
31 |
+
schema:
|
32 |
+
type: 'string'
|
33 |
+
summary: "This method can help with converting voice into the text."
|
34 |
+
responses:
|
35 |
+
200:
|
36 |
+
description: OK
|
37 |
+
content:
|
38 |
+
application/json:
|
39 |
+
schema:
|
40 |
+
$ref: "#/components/schemas/RecognizeResult"
|
41 |
+
400:
|
42 |
+
description: Bad Request
|
43 |
+
content:
|
44 |
+
application/json:
|
45 |
+
schema:
|
46 |
+
$ref: "#/components/schemas/ErrorObject"
|
47 |
+
post:
|
48 |
+
tags:
|
49 |
+
- Recognize API
|
50 |
+
parameters:
|
51 |
+
- name: 'url'
|
52 |
+
description: URL-link to voice message. Should be mp3, ogg or wav.
|
53 |
+
in: 'query'
|
54 |
+
schema:
|
55 |
+
type: 'string'
|
56 |
+
example: https://cdn-102.anonfiles.com/q8v0o5O5y8/3d62dac1-1671893935/j4893hg894g4.mp3
|
57 |
+
- name: 'file'
|
58 |
+
description: Upload file to recognize voice. **NOT SUPPORTED NOW**
|
59 |
+
in: 'query'
|
60 |
+
schema:
|
61 |
+
type: 'string'
|
62 |
+
- name: 'extendInfo'
|
63 |
+
description: Provide additional information or not.
|
64 |
+
in: 'query'
|
65 |
+
schema:
|
66 |
+
type: 'string'
|
67 |
+
default: False
|
68 |
+
example: False
|
69 |
+
- name: 'signature'
|
70 |
+
description: Special access key.
|
71 |
+
in: 'query'
|
72 |
+
schema:
|
73 |
+
type: 'string'
|
74 |
+
summary: "This method can help with converting voice into the text."
|
75 |
+
responses:
|
76 |
+
200:
|
77 |
+
description: OK
|
78 |
+
content:
|
79 |
+
application/json:
|
80 |
+
schema:
|
81 |
+
$ref: "#/components/schemas/RecognizeResult"
|
82 |
+
400:
|
83 |
+
description: Bad Request
|
84 |
+
content:
|
85 |
+
application/json:
|
86 |
+
schema:
|
87 |
+
$ref: "#/components/schemas/ErrorObject"
|
88 |
+
/yt/api/v1/search:
|
89 |
+
get:
|
90 |
+
tags:
|
91 |
+
- "Youtube: Becoming Music Platform"
|
92 |
+
parameters:
|
93 |
+
- name: 'query'
|
94 |
+
description: Query for YouTube to find videos.
|
95 |
+
in: 'query'
|
96 |
+
schema:
|
97 |
+
type: 'string'
|
98 |
+
example: never gonna give you up
|
99 |
+
- name: 'signature'
|
100 |
+
description: Special access key.
|
101 |
+
in: 'query'
|
102 |
+
schema:
|
103 |
+
type: 'string'
|
104 |
+
summary: "This method can help with searching videos on YouTube."
|
105 |
+
responses:
|
106 |
+
200:
|
107 |
+
description: OK
|
108 |
+
content:
|
109 |
+
application/json:
|
110 |
+
schema:
|
111 |
+
$ref: "#/components/schemas/YTSearchResult"
|
112 |
+
400:
|
113 |
+
description: Bad Request
|
114 |
+
content:
|
115 |
+
application/json:
|
116 |
+
schema:
|
117 |
+
$ref: "#/components/schemas/ErrorObject"
|
118 |
+
post:
|
119 |
+
tags:
|
120 |
+
- "Youtube: Becoming Music Platform"
|
121 |
+
parameters:
|
122 |
+
- name: 'query'
|
123 |
+
description: Query for YouTube to find videos.
|
124 |
+
in: 'query'
|
125 |
+
schema:
|
126 |
+
type: 'string'
|
127 |
+
example: never gonna give you up
|
128 |
+
- name: 'signature'
|
129 |
+
description: Special access key.
|
130 |
+
in: 'query'
|
131 |
+
schema:
|
132 |
+
type: 'string'
|
133 |
+
summary: "This method can help with searching videos on YouTube."
|
134 |
+
responses:
|
135 |
+
200:
|
136 |
+
description: OK
|
137 |
+
content:
|
138 |
+
application/json:
|
139 |
+
schema:
|
140 |
+
$ref: "#/components/schemas/YTSearchResult"
|
141 |
+
400:
|
142 |
+
description: Bad Request
|
143 |
+
content:
|
144 |
+
application/json:
|
145 |
+
schema:
|
146 |
+
$ref: "#/components/schemas/ErrorObject"
|
147 |
+
components:
|
148 |
+
schemas:
|
149 |
+
ErrorObject:
|
150 |
+
type: object
|
151 |
+
properties:
|
152 |
+
status:
|
153 |
+
type: string
|
154 |
+
example: error
|
155 |
+
details:
|
156 |
+
type: object
|
157 |
+
properties:
|
158 |
+
error_code:
|
159 |
+
type: int
|
160 |
+
example: 103
|
161 |
+
error_details:
|
162 |
+
type: string
|
163 |
+
example: No signature
|
164 |
+
RecognizeResult:
|
165 |
+
type: object
|
166 |
+
properties:
|
167 |
+
status:
|
168 |
+
type: string
|
169 |
+
example: ok
|
170 |
+
result:
|
171 |
+
type: string
|
172 |
+
example: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean condimentum neque quis enim bibendum, ut molestie magna gravida. Donec et felis eget lacus sodales convallis. Quisque vitae erat et leo lobortis iaculis. Maecenas a lectus vitae metus fringilla luctus. Morbi sed pellentesque elit. Phasellus bibendum et urna sed elementum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus."
|
173 |
+
YTSearchResult:
|
174 |
+
type: object
|
175 |
+
properties:
|
176 |
+
status:
|
177 |
+
type: string
|
178 |
+
example: ok
|
179 |
+
query:
|
180 |
+
type: string
|
181 |
+
example: never gonna give you up
|
182 |
+
videoIds:
|
183 |
+
type: object
|
184 |
+
properties:
|
185 |
+
"0":
|
186 |
+
type: string
|
187 |
+
example: dQw4w9WgXcQ
|
188 |
+
"1":
|
189 |
+
type: string
|
190 |
+
example: GtL1huin9EE
|
191 |
+
"2":
|
192 |
+
type: string
|
193 |
+
example: uXV-IaR_vNE
|
static/favicon.ico
ADDED
static/full/.ogg
ADDED
Binary file (623 kB). View file
|
|
static/template.yaml
ADDED
@@ -0,0 +1,652 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
openapi: 3.0.0
|
2 |
+
info:
|
3 |
+
title: Providing Examples
|
4 |
+
description: Providing Examples
|
5 |
+
version: 1.0.0
|
6 |
+
paths:
|
7 |
+
/multiple-examples-in-request-parameters/{path-param-1}/{path-param-2}:
|
8 |
+
get:
|
9 |
+
tags:
|
10 |
+
- Providing Examples
|
11 |
+
parameters:
|
12 |
+
- name: 'path-param-1'
|
13 |
+
in: 'path'
|
14 |
+
schema:
|
15 |
+
type: 'string'
|
16 |
+
default: "p1-opt-2"
|
17 |
+
examples:
|
18 |
+
example1:
|
19 |
+
value: "p1-opt-1"
|
20 |
+
example2:
|
21 |
+
value: "p1-opt-2"
|
22 |
+
- name: 'path-param-2'
|
23 |
+
in: 'path'
|
24 |
+
schema:
|
25 |
+
type: 'string'
|
26 |
+
examples:
|
27 |
+
example1:
|
28 |
+
value: "p2-opt-1"
|
29 |
+
example2:
|
30 |
+
value: "p2-opt-2"
|
31 |
+
- name: 'age'
|
32 |
+
description: Single Example
|
33 |
+
in: 'query'
|
34 |
+
schema:
|
35 |
+
type: 'number'
|
36 |
+
example: 24
|
37 |
+
- name: 'country-code'
|
38 |
+
description: Multiple examples _(Notice `us` do not have a summary)_
|
39 |
+
in: 'query'
|
40 |
+
schema:
|
41 |
+
type: 'string'
|
42 |
+
default: " "
|
43 |
+
examples:
|
44 |
+
example1:
|
45 |
+
value: "uk"
|
46 |
+
summary: "United Kingdom"
|
47 |
+
example2:
|
48 |
+
value: "us"
|
49 |
+
example3:
|
50 |
+
value: "ch"
|
51 |
+
summary: "China"
|
52 |
+
- name: 'marital-status'
|
53 |
+
in: 'query'
|
54 |
+
schema:
|
55 |
+
type: 'string'
|
56 |
+
default: "unmarried"
|
57 |
+
examples:
|
58 |
+
example1:
|
59 |
+
value: "married"
|
60 |
+
example2:
|
61 |
+
value: "unmarried"
|
62 |
+
example3:
|
63 |
+
value: "widowed"
|
64 |
+
- name: luckyNumbers
|
65 |
+
in: query
|
66 |
+
schema:
|
67 |
+
type: array
|
68 |
+
items:
|
69 |
+
type: number
|
70 |
+
minItems: 4
|
71 |
+
maxItems: 4
|
72 |
+
examples:
|
73 |
+
- ""
|
74 |
+
- " "
|
75 |
+
- [10]
|
76 |
+
- [10, 20, 30, 40]
|
77 |
+
|
78 |
+
/multiple-examples-by-response-type:
|
79 |
+
get:
|
80 |
+
description: Multiple Examples provide for each media-type (`application/json` or `application/json`)
|
81 |
+
tags:
|
82 |
+
- Providing Examples
|
83 |
+
responses:
|
84 |
+
'200':
|
85 |
+
description: Successful operation
|
86 |
+
content:
|
87 |
+
application/json:
|
88 |
+
schema:
|
89 |
+
type: object
|
90 |
+
properties:
|
91 |
+
age:
|
92 |
+
description: Person Age
|
93 |
+
type: integer
|
94 |
+
fullName:
|
95 |
+
description: Person Full name
|
96 |
+
type: object
|
97 |
+
properties:
|
98 |
+
firstName:
|
99 |
+
description: First name
|
100 |
+
type: string
|
101 |
+
lastName:
|
102 |
+
description: Last name
|
103 |
+
type: string
|
104 |
+
examples:
|
105 |
+
valid-json:
|
106 |
+
summary: Example with Valid JSON String
|
107 |
+
description: If valid JSON is provided in the example, It will be displayed in JSON tree form. Allowing copy/expand/collapse functionality
|
108 |
+
value: |
|
109 |
+
{
|
110 |
+
"person": {
|
111 |
+
"fullName": {
|
112 |
+
"firstName": "Mickey",
|
113 |
+
"lastName": "Mouse"
|
114 |
+
},
|
115 |
+
"age": "9"
|
116 |
+
}
|
117 |
+
}
|
118 |
+
invalid-json:
|
119 |
+
summary: Example with Invalid JSON String
|
120 |
+
description: Invalid JSON is displayed in text-area as is
|
121 |
+
value: |
|
122 |
+
{
|
123 |
+
person: {
|
124 |
+
fullName: {
|
125 |
+
firstName: Donald,
|
126 |
+
lastName: Duck
|
127 |
+
},
|
128 |
+
age: 10
|
129 |
+
}
|
130 |
+
}
|
131 |
+
as-object:
|
132 |
+
summary: Example specified as object
|
133 |
+
value:
|
134 |
+
fullName:
|
135 |
+
firstName: Donald
|
136 |
+
lastName: Duck
|
137 |
+
age: 10
|
138 |
+
application/xml:
|
139 |
+
schema:
|
140 |
+
type: object
|
141 |
+
properties:
|
142 |
+
age:
|
143 |
+
description: Person Age
|
144 |
+
type: integer
|
145 |
+
fullName:
|
146 |
+
description: Person Full name
|
147 |
+
type: object
|
148 |
+
properties:
|
149 |
+
firstName:
|
150 |
+
description: First name
|
151 |
+
type: string
|
152 |
+
lastName:
|
153 |
+
description: Last name
|
154 |
+
type: string
|
155 |
+
examples:
|
156 |
+
example-1:
|
157 |
+
description: Exmple 1 Description
|
158 |
+
value: |
|
159 |
+
<root>
|
160 |
+
<person>
|
161 |
+
<fullName>
|
162 |
+
<firstName> Mickey </firstName>
|
163 |
+
<lastName> Mouse </lastName>
|
164 |
+
</fullName>
|
165 |
+
<age> 9 </age>
|
166 |
+
</person>
|
167 |
+
</root>
|
168 |
+
/single-example-by-response-type:
|
169 |
+
get:
|
170 |
+
summary: Single Example at schema Level
|
171 |
+
tags:
|
172 |
+
- Providing Examples
|
173 |
+
responses:
|
174 |
+
'200':
|
175 |
+
description: Successful operation
|
176 |
+
content:
|
177 |
+
application/json:
|
178 |
+
schema:
|
179 |
+
type: object
|
180 |
+
properties:
|
181 |
+
age:
|
182 |
+
description: Person Age
|
183 |
+
type: integer
|
184 |
+
fullName:
|
185 |
+
description: Person Full name
|
186 |
+
type: object
|
187 |
+
properties:
|
188 |
+
firstName:
|
189 |
+
description: First name
|
190 |
+
type: string
|
191 |
+
lastName:
|
192 |
+
description: Last name
|
193 |
+
type: string
|
194 |
+
example: |
|
195 |
+
{
|
196 |
+
age: 10,
|
197 |
+
fullName: {
|
198 |
+
firstName: Donald,
|
199 |
+
lastName: Duck
|
200 |
+
}
|
201 |
+
}
|
202 |
+
/example-with-array-1:
|
203 |
+
get:
|
204 |
+
summary: Single Example at schema Level
|
205 |
+
tags:
|
206 |
+
- Providing Examples
|
207 |
+
responses:
|
208 |
+
'200':
|
209 |
+
description: Successful operation
|
210 |
+
content:
|
211 |
+
application/json:
|
212 |
+
schema:
|
213 |
+
$ref: "#/components/schemas/ArrayOfInt-1"
|
214 |
+
/example-with-array-2:
|
215 |
+
get:
|
216 |
+
summary: Single Example at schema Level
|
217 |
+
tags:
|
218 |
+
- Providing Examples
|
219 |
+
responses:
|
220 |
+
'200':
|
221 |
+
description: Successful operation
|
222 |
+
content:
|
223 |
+
application/json:
|
224 |
+
schema:
|
225 |
+
$ref: "#/components/schemas/ArrayOfInt-2"
|
226 |
+
|
227 |
+
/object-example-for-a-schema:
|
228 |
+
get:
|
229 |
+
summary: Single example having invalid JSON, under a Schema
|
230 |
+
tags:
|
231 |
+
- Providing Examples
|
232 |
+
responses:
|
233 |
+
'200':
|
234 |
+
description: Successful operation
|
235 |
+
content:
|
236 |
+
application/json:
|
237 |
+
schema:
|
238 |
+
type: object
|
239 |
+
properties:
|
240 |
+
age:
|
241 |
+
description: Person Age
|
242 |
+
type: integer
|
243 |
+
fullName:
|
244 |
+
description: Person Full name
|
245 |
+
type: object
|
246 |
+
properties:
|
247 |
+
firstName:
|
248 |
+
description: First name
|
249 |
+
type: string
|
250 |
+
lastName:
|
251 |
+
description: Last name
|
252 |
+
type: string
|
253 |
+
example: |
|
254 |
+
{
|
255 |
+
person: {
|
256 |
+
fullName: {
|
257 |
+
firstName: Donald,
|
258 |
+
lastName: Duck
|
259 |
+
},
|
260 |
+
age: 10
|
261 |
+
}
|
262 |
+
}
|
263 |
+
/array-example-for-a-schema:
|
264 |
+
get:
|
265 |
+
summary: Single Example of Type Array Under a Schema
|
266 |
+
tags:
|
267 |
+
- Providing Examples
|
268 |
+
responses:
|
269 |
+
'200':
|
270 |
+
description: An array of currency codes
|
271 |
+
content:
|
272 |
+
application/json:
|
273 |
+
schema:
|
274 |
+
$ref: "#/components/schemas/currencies"
|
275 |
+
/example-with-simple-object:
|
276 |
+
get:
|
277 |
+
summary: Single Example of Type Array Under a Schema
|
278 |
+
tags:
|
279 |
+
- Providing Examples
|
280 |
+
responses:
|
281 |
+
'200':
|
282 |
+
description: An array of currency codes
|
283 |
+
content:
|
284 |
+
application/json:
|
285 |
+
schema:
|
286 |
+
$ref: "#/components/schemas/PersonObject"
|
287 |
+
/per-field-example-with-root-as-object:
|
288 |
+
get:
|
289 |
+
summary: Root node of the example is an object. and the object is constituted using field level example
|
290 |
+
tags:
|
291 |
+
- Providing Examples
|
292 |
+
responses:
|
293 |
+
'200':
|
294 |
+
description: Successful operation
|
295 |
+
content:
|
296 |
+
application/json:
|
297 |
+
schema:
|
298 |
+
type: object
|
299 |
+
properties:
|
300 |
+
age:
|
301 |
+
description: Person Age
|
302 |
+
type: integer
|
303 |
+
example: 8
|
304 |
+
fullName:
|
305 |
+
description: Person Full name
|
306 |
+
type: object
|
307 |
+
properties:
|
308 |
+
firstName:
|
309 |
+
description: First name
|
310 |
+
type: string
|
311 |
+
example: 'Daisy'
|
312 |
+
lastName:
|
313 |
+
description: Last name
|
314 |
+
type: string
|
315 |
+
example: 'Duck'
|
316 |
+
dependents:
|
317 |
+
type: array
|
318 |
+
items:
|
319 |
+
type: object
|
320 |
+
properties:
|
321 |
+
dependentName:
|
322 |
+
type: string
|
323 |
+
relation:
|
324 |
+
type: string
|
325 |
+
age:
|
326 |
+
type: number
|
327 |
+
/per-field-example-with-root-as-array:
|
328 |
+
get:
|
329 |
+
summary: Root node of the example is an array. and the object is constituted using field level example
|
330 |
+
tags:
|
331 |
+
- Providing Examples
|
332 |
+
responses:
|
333 |
+
'200':
|
334 |
+
description: Successful operation
|
335 |
+
content:
|
336 |
+
application/json:
|
337 |
+
schema:
|
338 |
+
type: array
|
339 |
+
items:
|
340 |
+
type: object
|
341 |
+
properties:
|
342 |
+
dependentName:
|
343 |
+
type: string
|
344 |
+
relation:
|
345 |
+
type: string
|
346 |
+
age:
|
347 |
+
type: number
|
348 |
+
example:
|
349 |
+
dependentName: Natasha
|
350 |
+
relation: wife
|
351 |
+
age: 28
|
352 |
+
/example-with-refs:
|
353 |
+
get:
|
354 |
+
description: |
|
355 |
+
When a Schema definition is `provided` as a ref
|
356 |
+
(provide the example at schema-level)
|
357 |
+
tags:
|
358 |
+
- Providing Examples
|
359 |
+
responses:
|
360 |
+
'200':
|
361 |
+
description: Successful operation
|
362 |
+
content:
|
363 |
+
application/json:
|
364 |
+
schema:
|
365 |
+
type: array
|
366 |
+
items:
|
367 |
+
$ref: '#/components/schemas/cost'
|
368 |
+
examples:
|
369 |
+
USD:
|
370 |
+
description: Cost in `US Dollars`
|
371 |
+
value: |
|
372 |
+
{
|
373 |
+
amount: 10,
|
374 |
+
currency: USD
|
375 |
+
}
|
376 |
+
INR:
|
377 |
+
description: Cost in `Indian Rupees`
|
378 |
+
value: |
|
379 |
+
{
|
380 |
+
amount: 700,
|
381 |
+
currency: INR
|
382 |
+
}
|
383 |
+
/multiple-example-in-request-body:
|
384 |
+
post:
|
385 |
+
summary: Request body with multiple examples
|
386 |
+
tags:
|
387 |
+
- Providing Examples
|
388 |
+
requestBody:
|
389 |
+
description: Request body containing **multiple** examples
|
390 |
+
required: true
|
391 |
+
content:
|
392 |
+
application/json:
|
393 |
+
schema:
|
394 |
+
type: array
|
395 |
+
items:
|
396 |
+
$ref: '#/components/schemas/cost'
|
397 |
+
examples:
|
398 |
+
USD:
|
399 |
+
description: Cost in `US Dollars`
|
400 |
+
value: |
|
401 |
+
{
|
402 |
+
amount: 10,
|
403 |
+
currency: USD
|
404 |
+
}
|
405 |
+
INR:
|
406 |
+
description: Cost in `Indian Rupees`
|
407 |
+
value: |
|
408 |
+
{
|
409 |
+
amount: 700,
|
410 |
+
currency: INR
|
411 |
+
}
|
412 |
+
/object-containg-array-property-with-example:
|
413 |
+
get:
|
414 |
+
summary: Object schema with array type property containing example
|
415 |
+
tags:
|
416 |
+
- Providing Examples
|
417 |
+
responses:
|
418 |
+
200:
|
419 |
+
description: Object with array type property containing example
|
420 |
+
content:
|
421 |
+
application/json:
|
422 |
+
schema:
|
423 |
+
$ref: "#/components/schemas/ObjectWithArrayPropExample"
|
424 |
+
/examples-anyOf:
|
425 |
+
get:
|
426 |
+
tags:
|
427 |
+
- Providing Examples
|
428 |
+
summary: AnyOf schemas with examples as part of the subschema
|
429 |
+
responses:
|
430 |
+
'200':
|
431 |
+
description: AnyOf schemas with examples as part of the subschema
|
432 |
+
content:
|
433 |
+
application/problem+json:
|
434 |
+
schema:
|
435 |
+
anyOf:
|
436 |
+
- title: AnyOf example 1
|
437 |
+
description: First example
|
438 |
+
type: object
|
439 |
+
properties:
|
440 |
+
foo:
|
441 |
+
type: string
|
442 |
+
bar:
|
443 |
+
type: integer
|
444 |
+
example:
|
445 |
+
foo: foo
|
446 |
+
bar: 42
|
447 |
+
- title: Second anyOf
|
448 |
+
description: Another example
|
449 |
+
type: array
|
450 |
+
items:
|
451 |
+
type: object
|
452 |
+
properties:
|
453 |
+
foo:
|
454 |
+
type: string
|
455 |
+
quux:
|
456 |
+
type: array
|
457 |
+
items:
|
458 |
+
type: number
|
459 |
+
example:
|
460 |
+
foo: foo
|
461 |
+
quux: [ 42, 24 ]
|
462 |
+
- title: No example defined
|
463 |
+
type: array
|
464 |
+
items:
|
465 |
+
type: object
|
466 |
+
properties:
|
467 |
+
foo:
|
468 |
+
type: string
|
469 |
+
quux:
|
470 |
+
type: array
|
471 |
+
items:
|
472 |
+
type: number
|
473 |
+
/examples-anyOf-with-general-properties:
|
474 |
+
get:
|
475 |
+
tags:
|
476 |
+
- Providing Examples
|
477 |
+
summary: AnyOf schemas with general properties
|
478 |
+
responses:
|
479 |
+
'200':
|
480 |
+
description: AnyOf schemas with general properties
|
481 |
+
content:
|
482 |
+
application/problem+json:
|
483 |
+
schema:
|
484 |
+
title: A composed object
|
485 |
+
type: object
|
486 |
+
properties:
|
487 |
+
common:
|
488 |
+
type: string
|
489 |
+
other:
|
490 |
+
type: number
|
491 |
+
anyOf:
|
492 |
+
- title: Schema 1
|
493 |
+
type: object
|
494 |
+
properties:
|
495 |
+
foo:
|
496 |
+
type: string
|
497 |
+
bar:
|
498 |
+
type: integer
|
499 |
+
example:
|
500 |
+
foo: foo
|
501 |
+
bar: 42
|
502 |
+
- title: Second schema
|
503 |
+
type: object
|
504 |
+
properties:
|
505 |
+
baz:
|
506 |
+
type: string
|
507 |
+
format: url
|
508 |
+
/examples-oneOf:
|
509 |
+
get:
|
510 |
+
tags:
|
511 |
+
- Providing Examples
|
512 |
+
summary: OneOf schema with examples as part of the subschema
|
513 |
+
responses:
|
514 |
+
'200':
|
515 |
+
description: OneOf schema with examples as part of the subschema
|
516 |
+
content:
|
517 |
+
application/problem+json:
|
518 |
+
schema:
|
519 |
+
oneOf:
|
520 |
+
- title: Schema 1
|
521 |
+
type: object
|
522 |
+
properties:
|
523 |
+
foo:
|
524 |
+
type: string
|
525 |
+
bar:
|
526 |
+
type: integer
|
527 |
+
example:
|
528 |
+
foo: foo
|
529 |
+
bar: 42
|
530 |
+
- title: Second schema
|
531 |
+
type: object
|
532 |
+
properties:
|
533 |
+
baz:
|
534 |
+
type: string
|
535 |
+
format: url
|
536 |
+
/examples-allOf:
|
537 |
+
get:
|
538 |
+
tags:
|
539 |
+
- Providing Examples
|
540 |
+
summary: AllOf schemas with examples as part of the subschema
|
541 |
+
responses:
|
542 |
+
'200':
|
543 |
+
description: AllOf schemas with examples as part of the subschema
|
544 |
+
content:
|
545 |
+
application/problem+json:
|
546 |
+
schema:
|
547 |
+
allOf:
|
548 |
+
- title: Schema 1
|
549 |
+
type: object
|
550 |
+
properties:
|
551 |
+
foo:
|
552 |
+
type: string
|
553 |
+
bar:
|
554 |
+
type: integer
|
555 |
+
- title: Second schema
|
556 |
+
type: object
|
557 |
+
properties:
|
558 |
+
baz:
|
559 |
+
type: string
|
560 |
+
format: url
|
561 |
+
/examples-allOf-anyOf:
|
562 |
+
get:
|
563 |
+
tags:
|
564 |
+
- Providing Examples
|
565 |
+
summary: Combination of allOf & nested anyOf schemas
|
566 |
+
responses:
|
567 |
+
'200':
|
568 |
+
description: Combination of allOf & nested anyOf schemas
|
569 |
+
content:
|
570 |
+
application/problem+json:
|
571 |
+
schema:
|
572 |
+
allOf:
|
573 |
+
- title: Schema 1
|
574 |
+
type: object
|
575 |
+
properties:
|
576 |
+
foo:
|
577 |
+
type: string
|
578 |
+
bar:
|
579 |
+
type: integer
|
580 |
+
- title: Second schema
|
581 |
+
anyOf:
|
582 |
+
- type: object
|
583 |
+
properties:
|
584 |
+
baz:
|
585 |
+
type: string
|
586 |
+
format: url
|
587 |
+
- type: object
|
588 |
+
properties:
|
589 |
+
foobar:
|
590 |
+
type: string
|
591 |
+
components:
|
592 |
+
schemas:
|
593 |
+
cost:
|
594 |
+
type: object
|
595 |
+
properties:
|
596 |
+
amount:
|
597 |
+
type: integer
|
598 |
+
description: Amount
|
599 |
+
currency:
|
600 |
+
description: Currency Code
|
601 |
+
type: string
|
602 |
+
currencies:
|
603 |
+
type: array
|
604 |
+
items:
|
605 |
+
type: object
|
606 |
+
properties:
|
607 |
+
currencyCode:
|
608 |
+
type: string
|
609 |
+
evaluationDate:
|
610 |
+
type: string
|
611 |
+
format: date-time
|
612 |
+
example:
|
613 |
+
- currencyCode: USD
|
614 |
+
evaluationDate: '2017-07-21T17:32:28Z'
|
615 |
+
- currencyCode: INR
|
616 |
+
evaluationDate: '2017-07-21T17:32:28Z'
|
617 |
+
ArrayOfInt-1:
|
618 |
+
type: array
|
619 |
+
items:
|
620 |
+
type: integer
|
621 |
+
format: int64
|
622 |
+
example: [1, 2, 3, 4]
|
623 |
+
ArrayOfInt-2:
|
624 |
+
type: array
|
625 |
+
items:
|
626 |
+
type: integer
|
627 |
+
format: int64
|
628 |
+
example: 1
|
629 |
+
PersonObject:
|
630 |
+
type: object
|
631 |
+
properties:
|
632 |
+
name:
|
633 |
+
type: string
|
634 |
+
age:
|
635 |
+
type: integer
|
636 |
+
example:
|
637 |
+
name: name-1
|
638 |
+
age: 1
|
639 |
+
ObjectWithArrayPropExample:
|
640 |
+
type: object
|
641 |
+
properties:
|
642 |
+
numberProp:
|
643 |
+
type: number
|
644 |
+
example: 1000
|
645 |
+
stringProp:
|
646 |
+
type: string
|
647 |
+
enum: [value0, value1]
|
648 |
+
arrayProp:
|
649 |
+
type: array
|
650 |
+
items:
|
651 |
+
type: number
|
652 |
+
example: [0, 1, 2]
|
templates/4a1504d326b35eaad3b9d4f48b5119a6/403.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<html><head><title>403 Forbidden</title></head><body><center><h1>403 Forbidden</h1></center><hr><center>mangoo</center></body></html>
|
templates/4a1504d326b35eaad3b9d4f48b5119a6/404.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<html><head><title>404 Not Found</title></head><body><center><h1>404 Not Found</h1></center><hr><center>mangoo</center></body></html>
|
templates/4a1504d326b35eaad3b9d4f48b5119a6/429.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<html><head><title>429 Too Many Requests</title></head><body><center><h1>429 Too Many Requests</h1></center><hr><center>mangoo</center></body></html>
|
templates/4a1504d326b35eaad3b9d4f48b5119a6/502.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<html><head><title>502 Bad Gateway</title></head><body><center><h1>502 Bad Gateway</h1></center><hr><center>mangoo</center></body></html>
|
templates/badgateway.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<html><head><title>502 Bad Gateway</title></head><body><center><h1>502 Bad Gateway</h1></center><hr><center>mangoo</center></body></html>
|
templates/forbidden.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<html><head><title>403 Forbidden</title></head><body><center><h1>403 Forbidden</h1></center><hr><center>mangoo</center></body></html>
|
templates/index.html
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!doctype html> <!-- Important: must specify -->
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>DNSZilla's FunAPI</title>
|
5 |
+
<style> body {background-color:#14191f;} </style>
|
6 |
+
<meta charset="utf-8">
|
7 |
+
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
|
8 |
+
<script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<rapi-doc
|
12 |
+
spec-url="/static/api.yaml"
|
13 |
+
theme="dark"
|
14 |
+
allow-try="false"
|
15 |
+
allow-search="false"
|
16 |
+
allow-authentication="false"
|
17 |
+
show-info="true"
|
18 |
+
show-header="false"
|
19 |
+
render-style="view"
|
20 |
+
bg-color="#14191f"
|
21 |
+
text-color="#aec2e0"
|
22 |
+
primary-color="#c7d8f2"
|
23 |
+
> <br> </rapi-doc>
|
24 |
+
</body>
|
25 |
+
</html>
|
templates/notfound.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<html><head><title>404 Not Found</title></head><body><center><h1>404 Not Found</h1></center><hr><center>mangoo</center></body></html>
|
templates/ratelimit.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<html><head><title>429 Too Many Requests</title></head><body><center><h1>429 Too Many Requests</h1></center><hr><center>mangoo</center></body></html>
|