imperialwool commited on
Commit
66ca64a
1 Parent(s): fd57bb9

Upload 28 files

Browse files
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>