mirror of
https://github.com/leon-ai/leon.git
synced 2024-11-27 16:16:48 +03:00
feat(skill/akinator): backbone
This commit is contained in:
parent
aad9f3f1ef
commit
02a2f71470
@ -1,5 +1,20 @@
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/start",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/play",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/rematch",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/guess_the_number/setup",
|
||||
|
0
skills/games/akinator/README.md
Normal file
0
skills/games/akinator/README.md
Normal file
0
skills/games/akinator/memory/.gitkeep
Normal file
0
skills/games/akinator/memory/.gitkeep
Normal file
83
skills/games/akinator/nlu/en.json
Normal file
83
skills/games/akinator/nlu/en.json
Normal file
@ -0,0 +1,83 @@
|
||||
{
|
||||
"actions": {
|
||||
"start": {
|
||||
"type": "dialog",
|
||||
"utterance_samples": [
|
||||
"[Let's play|I want to play|I wanna play] with Akinator"
|
||||
],
|
||||
"answers": [
|
||||
"Alright, I'm calling my friend Akinator..."
|
||||
],
|
||||
"next_action": "guess"
|
||||
},
|
||||
"guess": {
|
||||
"type": "logic",
|
||||
"loop": {
|
||||
"expected_item": {
|
||||
"type": "resolver",
|
||||
"name": "answer"
|
||||
}
|
||||
},
|
||||
"suggestions": [
|
||||
"Yes",
|
||||
"No",
|
||||
"I don't know",
|
||||
"Probably",
|
||||
"Probably not"
|
||||
],
|
||||
"next_action": "replay"
|
||||
},
|
||||
"replay": {
|
||||
"type": "logic",
|
||||
"loop": {
|
||||
"expected_item": {
|
||||
"type": "resolver",
|
||||
"name": "affirmation_denial"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"resolvers": {
|
||||
"answer": {
|
||||
"intents": {
|
||||
"yes": {
|
||||
"utterance_samples": [
|
||||
"[Yes|Yep|Yup|Yeah]",
|
||||
"Sure",
|
||||
"Correct"
|
||||
],
|
||||
"value": "yes"
|
||||
},
|
||||
"no": {
|
||||
"utterance_samples": [
|
||||
"[No|Nope|Nah]"
|
||||
],
|
||||
"value": "no"
|
||||
},
|
||||
"idk": {
|
||||
"utterance_samples": [
|
||||
"I do not know",
|
||||
"Don't know",
|
||||
"Not sure"
|
||||
],
|
||||
"value": "idk"
|
||||
},
|
||||
"probably": {
|
||||
"utterance_samples": [
|
||||
"Probably",
|
||||
"Probably yes"
|
||||
],
|
||||
"value": "probably"
|
||||
},
|
||||
"probably_not": {
|
||||
"utterance_samples": [
|
||||
"Probably [no|not]"
|
||||
],
|
||||
"value": "probably_not"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"answers": {
|
||||
}
|
||||
}
|
11
skills/games/akinator/skill.json
Normal file
11
skills/games/akinator/skill.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "Akinator",
|
||||
"bridge": "python",
|
||||
"version": "1.0.0",
|
||||
"description": "Leon's friend, the Akinator genie will read your mind.",
|
||||
"author": {
|
||||
"name": "Louis Grenard",
|
||||
"email": "louis.grenard@gmail.com",
|
||||
"url": "https://github.com/louistiti"
|
||||
}
|
||||
}
|
29
skills/games/akinator/src/actions/guess.py
Normal file
29
skills/games/akinator/src/actions/guess.py
Normal file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import random
|
||||
|
||||
import utils
|
||||
from ..lib import akinator
|
||||
|
||||
def guess(params):
|
||||
aki = akinator.Akinator()
|
||||
|
||||
q = aki.start_game()
|
||||
|
||||
while aki.progression <= 80:
|
||||
a = input(q + "\n\t")
|
||||
if a == "b":
|
||||
try:
|
||||
q = aki.back()
|
||||
except akinator.CantGoBackAnyFurther:
|
||||
pass
|
||||
else:
|
||||
q = aki.answer(a)
|
||||
aki.win()
|
||||
|
||||
correct = input(f"It's {aki.first_guess['name']} ({aki.first_guess['description']})! Was I correct?\n{aki.first_guess['absolute_picture_path']}\n\t")
|
||||
if correct.lower() == "yes" or correct.lower() == "y":
|
||||
print("Yay\n")
|
||||
else:
|
||||
print("Oof\n")
|
7
skills/games/akinator/src/actions/replay.py
Normal file
7
skills/games/akinator/src/actions/replay.py
Normal file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import utils
|
||||
|
||||
def replay(params):
|
||||
"""TODO"""
|
6
skills/games/akinator/src/config.sample.json
Normal file
6
skills/games/akinator/src/config.sample.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"configurations": {
|
||||
"options": {},
|
||||
"credentials": {}
|
||||
}
|
||||
}
|
0
skills/games/akinator/src/lib/.gitkeep
Normal file
0
skills/games/akinator/src/lib/.gitkeep
Normal file
1
skills/games/akinator/src/lib/VERSION.txt
Normal file
1
skills/games/akinator/src/lib/VERSION.txt
Normal file
@ -0,0 +1 @@
|
||||
5.0.0
|
33
skills/games/akinator/src/lib/__init__.py
Normal file
33
skills/games/akinator/src/lib/__init__.py
Normal file
@ -0,0 +1,33 @@
|
||||
"""
|
||||
An API wrapper for the online game, Akinator, written in Python
|
||||
"""
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 NinjaSnail1080
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
from .akinator import Akinator
|
||||
from .exceptions import *
|
||||
import os
|
||||
|
||||
with open(os.path.join(os.path.dirname(__file__), "VERSION.txt")) as f:
|
||||
__version__ = f.read()
|
231
skills/games/akinator/src/lib/akinator.py
Normal file
231
skills/games/akinator/src/lib/akinator.py
Normal file
@ -0,0 +1,231 @@
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 NinjaSnail1080
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
import utils
|
||||
import exceptions
|
||||
import re
|
||||
import time
|
||||
import json
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
#* URLs for the API requests
|
||||
NEW_SESSION_URL = "https://{}/new_session?callback=jQuery331023608747682107778_{}&urlApiWs={}&partner=1&childMod={}&player=website-desktop&uid_ext_session={}&frontaddr={}&constraint=ETAT<>'AV'&soft_constraint={}&question_filter={}"
|
||||
ANSWER_URL = "https://{}/answer_api?callback=jQuery331023608747682107778_{}&urlApiWs={}&childMod={}&session={}&signature={}&step={}&answer={}&frontaddr={}&question_filter={}"
|
||||
BACK_URL = "{}/cancel_answer?callback=jQuery331023608747682107778_{}&childMod={}&session={}&signature={}&step={}&answer=-1&question_filter={}"
|
||||
WIN_URL = "{}/list?callback=jQuery331023608747682107778_{}&childMod={}&session={}&signature={}&step={}"
|
||||
|
||||
#* HTTP headers to use for the requests
|
||||
HEADERS = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) snap Chromium/81.0.4044.92 Chrome/81.0.4044.92 Safari/537.36",
|
||||
"x-requested-with": "XMLHttpRequest",
|
||||
}
|
||||
|
||||
|
||||
class Akinator():
|
||||
"""A class that represents an Akinator game.
|
||||
|
||||
The first thing you want to do after calling an instance of this class is to call "start_game()".
|
||||
"""
|
||||
def __init__(self):
|
||||
self.uri = None
|
||||
self.server = None
|
||||
self.session = None
|
||||
self.signature = None
|
||||
self.uid = None
|
||||
self.frontaddr = None
|
||||
self.child_mode = None
|
||||
self.question_filter = None
|
||||
self.timestamp = None
|
||||
|
||||
self.question = None
|
||||
self.progression = None
|
||||
self.step = None
|
||||
|
||||
self.first_guess = None
|
||||
self.guesses = None
|
||||
|
||||
def _update(self, resp, start=False):
|
||||
"""Update class variables"""
|
||||
|
||||
if start:
|
||||
self.session = int(resp["parameters"]["identification"]["session"])
|
||||
self.signature = int(resp["parameters"]["identification"]["signature"])
|
||||
self.question = str(resp["parameters"]["step_information"]["question"])
|
||||
self.progression = float(resp["parameters"]["step_information"]["progression"])
|
||||
self.step = int(resp["parameters"]["step_information"]["step"])
|
||||
else:
|
||||
self.question = str(resp["parameters"]["question"])
|
||||
self.progression = float(resp["parameters"]["progression"])
|
||||
self.step = int(resp["parameters"]["step"])
|
||||
|
||||
def _parse_response(self, response):
|
||||
"""Parse the JSON response and turn it into a Python object"""
|
||||
|
||||
return json.loads(",".join(response.split("(")[1::])[:-1])
|
||||
|
||||
def _get_session_info(self):
|
||||
"""Get uid and frontaddr from akinator.com/game"""
|
||||
|
||||
info_regex = re.compile("var uid_ext_session = '(.*)'\\;\\n.*var frontaddr = '(.*)'\\;")
|
||||
r = requests.get("https://en.akinator.com/game")
|
||||
|
||||
match = info_regex.search(r.text)
|
||||
self.uid, self.frontaddr = match.groups()[0], match.groups()[1]
|
||||
|
||||
def _auto_get_region(self, lang, theme):
|
||||
"""Automatically get the uri and server from akinator.com for the specified language and theme"""
|
||||
|
||||
server_regex = re.compile("[{\"translated_theme_name\":\"[\s\S]*\",\"urlWs\":\"https:\\\/\\\/srv[0-9]+\.akinator\.com:[0-9]+\\\/ws\",\"subject_id\":\"[0-9]+\"}]")
|
||||
uri = lang + ".akinator.com"
|
||||
|
||||
bad_list = ["https://srv12.akinator.com:9398/ws"]
|
||||
while True:
|
||||
r = requests.get("https://" + uri)
|
||||
|
||||
match = server_regex.search(r.text)
|
||||
parsed = json.loads(match.group().split("'arrUrlThemesToPlay', ")[-1])
|
||||
|
||||
if theme == "c":
|
||||
server = next((i for i in parsed if i["subject_id"] == "1"), None)["urlWs"]
|
||||
elif theme == "a":
|
||||
server = next((i for i in parsed if i["subject_id"] == "14"), None)["urlWs"]
|
||||
elif theme == "o":
|
||||
server = next((i for i in parsed if i["subject_id"] == "2"), None)["urlWs"]
|
||||
|
||||
if server not in bad_list:
|
||||
return {"uri": uri, "server": server}
|
||||
|
||||
def start_game(self, language=None, child_mode=False):
|
||||
"""Start an Akinator game. Run this function first before the others. Returns a string containing the first question
|
||||
|
||||
The "language" parameter can be left as None for English, the default language, or it can be set to one of the following (case-insensitive):
|
||||
- "en": English (default)
|
||||
- "en_animals": English server for guessing animals
|
||||
- "en_objects": English server for guessing objects
|
||||
- "ar": Arabic
|
||||
- "cn": Chinese
|
||||
- "de": German
|
||||
- "de_animals": German server for guessing animals
|
||||
- "es": Spanish
|
||||
- "es_animals": Spanish server for guessing animals
|
||||
- "fr": French
|
||||
- "fr_animals": French server for guessing animals
|
||||
- "fr_objects": French server for guessing objects
|
||||
- "il": Hebrew
|
||||
- "it": Italian
|
||||
- "it_animals": Italian server for guessing animals
|
||||
- "jp": Japanese
|
||||
- "jp_animals": Japanese server for guessing animals
|
||||
- "kr": Korean
|
||||
- "nl": Dutch
|
||||
- "pl": Polish
|
||||
- "pt": Portuguese
|
||||
- "ru": Russian
|
||||
- "tr": Turkish
|
||||
- "id": Indonesian
|
||||
You can also put the name of the language spelled out, like "spanish", "korean", "french_animals", etc.
|
||||
|
||||
The "child_mode" parameter is False by default. If it's set to True, then Akinator won't ask questions about things that are NSFW
|
||||
"""
|
||||
self.timestamp = time.time()
|
||||
region_info = self._auto_get_region(utils.get_lang_and_theme(language)["lang"], utils.get_lang_and_theme(language)["theme"])
|
||||
self.uri, self.server = region_info["uri"], region_info["server"]
|
||||
|
||||
self.child_mode = child_mode
|
||||
soft_constraint = "ETAT%3D%27EN%27" if self.child_mode else ""
|
||||
self.question_filter = "cat%3D1" if self.child_mode else ""
|
||||
|
||||
self._get_session_info()
|
||||
|
||||
r = requests.get(NEW_SESSION_URL.format(self.uri, self.timestamp, self.server, str(self.child_mode).lower(), self.uid, self.frontaddr, soft_constraint, self.question_filter), headers=HEADERS)
|
||||
resp = self._parse_response(r.text)
|
||||
|
||||
if resp["completion"] == "OK":
|
||||
self._update(resp, True)
|
||||
return self.question
|
||||
else:
|
||||
return raise_connection_error(resp["completion"])
|
||||
|
||||
def answer(self, ans):
|
||||
"""Answer the current question, which you can find with "Akinator.question". Returns a string containing the next question
|
||||
|
||||
The "ans" parameter must be one of these (case-insensitive):
|
||||
- "yes" OR "y" OR "0" for YES
|
||||
- "no" OR "n" OR "1" for NO
|
||||
- "i" OR "idk" OR "i dont know" OR "i don't know" OR "2" for I DON'T KNOW
|
||||
- "probably" OR "p" OR "3" for PROBABLY
|
||||
- "probably not" OR "pn" OR "4" for PROBABLY NOT
|
||||
"""
|
||||
ans = utils.ans_to_id(ans)
|
||||
|
||||
r = requests.get(ANSWER_URL.format(self.uri, self.timestamp, self.server, str(self.child_mode).lower(), self.session, self.signature, self.step, ans, self.frontaddr, self.question_filter), headers=HEADERS)
|
||||
resp = self._parse_response(r.text)
|
||||
|
||||
if resp["completion"] == "OK":
|
||||
self._update(resp)
|
||||
return self.question
|
||||
else:
|
||||
return utils.raise_connection_error(resp["completion"])
|
||||
|
||||
def back(self):
|
||||
"""Goes back to the previous question. Returns a string containing that question
|
||||
|
||||
If you're on the first question and you try to go back again, the CantGoBackAnyFurther exception will be raised
|
||||
"""
|
||||
if self.step == 0:
|
||||
raise exceptions.CantGoBackAnyFurther("You were on the first question and couldn't go back any further")
|
||||
|
||||
r = requests.get(BACK_URL.format(self.server, self.timestamp, str(self.child_mode).lower(), self.session, self.signature, self.step, self.question_filter), headers=HEADERS)
|
||||
resp = self._parse_response(r.text)
|
||||
|
||||
if resp["completion"] == "OK":
|
||||
self._update(resp)
|
||||
return self.question
|
||||
else:
|
||||
return utils.raise_connection_error(resp["completion"])
|
||||
|
||||
def win(self):
|
||||
"""Get Aki's guesses for who the person you're thinking of is based on your answers to the questions so far
|
||||
|
||||
Defines and returns the variable "Akinator.first_guess", a dictionary describing his first choice for who you're thinking about. The three most important values in the dict are "name" (character's name), "description" (description of character), and "absolute_picture_path" (direct link to image of character)
|
||||
|
||||
This function also defines "Akinator.guesses", which is a list of dictionaries containing his choices in order from most likely to least likely
|
||||
|
||||
It's recommended that you call this function when Aki's progression is above 85%, which is when he will have most likely narrowed it down to just one choice. You can get his current progression via "Akinator.progression"
|
||||
"""
|
||||
r = requests.get(WIN_URL.format(self.server, self.timestamp, str(self.child_mode).lower(), self.session, self.signature, self.step), headers=HEADERS)
|
||||
resp = self._parse_response(r.text)
|
||||
|
||||
if resp["completion"] == "OK":
|
||||
self.first_guess = resp["parameters"]["elements"][0]["element"]
|
||||
self.guesses = [g["element"] for g in resp["parameters"]["elements"]]
|
||||
return self.first_guess
|
||||
else:
|
||||
return utils.raise_connection_error(resp["completion"])
|
63
skills/games/akinator/src/lib/exceptions.py
Normal file
63
skills/games/akinator/src/lib/exceptions.py
Normal file
@ -0,0 +1,63 @@
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 NinjaSnail1080
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
|
||||
class InvalidAnswerError(ValueError):
|
||||
"""Raised when the user inputs an invalid answer"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidLanguageError(ValueError):
|
||||
"""Raised when the user inputs an invalid language"""
|
||||
pass
|
||||
|
||||
|
||||
class AkiConnectionFailure(Exception):
|
||||
"""Raised if the Akinator API fails to connect for some reason. Base class for AkiTimedOut, AkiNoQuestions, AkiServerDown, and AkiTechnicalError"""
|
||||
pass
|
||||
|
||||
|
||||
class AkiTimedOut(AkiConnectionFailure):
|
||||
"""Raised if the Akinator session times out. Derived from AkiConnectionFailure"""
|
||||
pass
|
||||
|
||||
|
||||
class AkiNoQuestions(AkiConnectionFailure):
|
||||
"""Raised if the Akinator API runs out of questions to ask. This will happen if "Akinator.step" is at 79 and the "answer" function is called again. Derived from AkiConnectionFailure"""
|
||||
pass
|
||||
|
||||
|
||||
class AkiServerDown(AkiConnectionFailure):
|
||||
"""Raised if Akinator's servers are down for the region you're running on. If this happens, try again later or use a different language. Derived from AkiConnectionFailure"""
|
||||
pass
|
||||
|
||||
|
||||
class AkiTechnicalError(AkiConnectionFailure):
|
||||
"""Raised if Aki's servers had a technical error. If this happens, try again later or use a different language. Derived from AkiConnectionFailure"""
|
||||
pass
|
||||
|
||||
|
||||
class CantGoBackAnyFurther(Exception):
|
||||
"""Raised when the user is on the first question and tries to go back further"""
|
||||
pass
|
124
skills/games/akinator/src/lib/utils.py
Normal file
124
skills/games/akinator/src/lib/utils.py
Normal file
@ -0,0 +1,124 @@
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 NinjaSnail1080
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
import exceptions
|
||||
|
||||
def ans_to_id(ans):
|
||||
"""Convert an input answer string into an Answer ID for Akinator"""
|
||||
|
||||
ans = str(ans).lower()
|
||||
if ans == "yes" or ans == "y" or ans == "0":
|
||||
return "0"
|
||||
elif ans == "no" or ans == "n" or ans == "1":
|
||||
return "1"
|
||||
elif ans == "i" or ans == "idk" or ans == "i dont know" or ans == "i don't know" or ans == "2":
|
||||
return "2"
|
||||
elif ans == "probably" or ans == "p" or ans == "3":
|
||||
return "3"
|
||||
elif ans == "probably not" or ans == "pn" or ans == "4":
|
||||
return "4"
|
||||
else:
|
||||
raise exceptions.InvalidAnswerError("""
|
||||
You put "{}", which is an invalid answer.
|
||||
The answer must be one of these:
|
||||
- "yes" OR "y" OR "0" for YES
|
||||
- "no" OR "n" OR "1" for NO
|
||||
- "i" OR "idk" OR "i dont know" OR "i don't know" OR "2" for I DON'T KNOW
|
||||
- "probably" OR "p" OR "3" for PROBABLY
|
||||
- "probably not" OR "pn" OR "4" for PROBABLY NOT
|
||||
""".format(ans))
|
||||
|
||||
|
||||
def get_lang_and_theme(lang=None):
|
||||
"""Returns the language code and theme based on what is input"""
|
||||
|
||||
if lang is None:
|
||||
return {"lang": "en", "theme": "c"}
|
||||
|
||||
lang = str(lang).lower()
|
||||
if lang == "en" or lang == "english":
|
||||
return {"lang": "en", "theme": "c"}
|
||||
elif lang == "en_animals" or lang == "english_animals":
|
||||
return {"lang": "en", "theme": "a"}
|
||||
elif lang == "en_objects" or lang == "english_objects":
|
||||
return {"lang": "en", "theme": "o"}
|
||||
elif lang == "ar" or lang == "arabic":
|
||||
return {"lang": "ar", "theme": "c"}
|
||||
elif lang == "cn" or lang == "chinese":
|
||||
return {"lang": "cn", "theme": "c"}
|
||||
elif lang == "de" or lang == "german":
|
||||
return {"lang": "de", "theme": "c"}
|
||||
elif lang == "de_animals" or lang == "german_animals":
|
||||
return {"lang": "de", "theme": "a"}
|
||||
elif lang == "es" or lang == "spanish":
|
||||
return {"lang": "es", "theme": "c"}
|
||||
elif lang == "es_animals" or lang == "spanish_animals":
|
||||
return {"lang": "es", "theme": "a"}
|
||||
elif lang == "fr" or lang == "french":
|
||||
return {"lang": "fr", "theme": "c"}
|
||||
elif lang == "fr_animals" or lang == "french_animals":
|
||||
return {"lang": "fr", "theme": "a"}
|
||||
elif lang == "fr_objects" or lang == "french_objects":
|
||||
return {"lang": "fr", "theme": "o"}
|
||||
elif lang == "il" or lang == "hebrew":
|
||||
return {"lang": "il", "theme": "c"}
|
||||
elif lang == "it" or lang == "italian":
|
||||
return {"lang": "it", "theme": "c"}
|
||||
elif lang == "it_animals" or lang == "italian_animals":
|
||||
return {"lang": "it", "theme": "a"}
|
||||
elif lang == "jp" or lang == "japanese":
|
||||
return {"lang": "jp", "theme": "c"}
|
||||
elif lang == "jp_animals" or lang == "japanese_animals":
|
||||
return {"lang": "jp", "theme": "a"}
|
||||
elif lang == "kr" or lang == "korean":
|
||||
return {"lang": "kr", "theme": "c"}
|
||||
elif lang == "nl" or lang == "dutch":
|
||||
return {"lang": "nl", "theme": "c"}
|
||||
elif lang == "pl" or lang == "polish":
|
||||
return {"lang": "pl", "theme": "c"}
|
||||
elif lang == "pt" or lang == "portuguese":
|
||||
return {"lang": "pt", "theme": "c"}
|
||||
elif lang == "ru" or lang == "russian":
|
||||
return {"lang": "ru", "theme": "c"}
|
||||
elif lang == "tr" or lang == "turkish":
|
||||
return {"lang": "tr", "theme": "c"}
|
||||
elif lang == "id" or lang == "indonesian":
|
||||
return {"lang": "id", "theme": "c"}
|
||||
else:
|
||||
raise exceptions.InvalidLanguageError("You put \"{}\", which is an invalid language.".format(lang))
|
||||
|
||||
|
||||
def raise_connection_error(response):
|
||||
"""Raise the proper error if the API failed to connect"""
|
||||
|
||||
if response == "KO - SERVER DOWN":
|
||||
raise exception.AkiServerDown("Akinator's servers are down in this region. Try again later or use a different language")
|
||||
elif response == "KO - TECHNICAL ERROR":
|
||||
raise exception.AkiTechnicalError("Akinator's servers have had a technical error. Try again later or use a different language")
|
||||
elif response == "KO - TIMEOUT":
|
||||
raise exceptions.AkiTimedOut("Your Akinator session has timed out")
|
||||
elif response == "KO - ELEM LIST IS EMPTY" or response == "WARN - NO QUESTION":
|
||||
raise exceptions.AkiNoQuestions("\"Akinator.step\" reached 79. No more questions")
|
||||
else:
|
||||
raise exceptions.AkiConnectionFailure("An unknown error has occured. Server response: {}".format(response))
|
0
skills/games/akinator/test/.gitkeep
Normal file
0
skills/games/akinator/test/.gitkeep
Normal file
Loading…
Reference in New Issue
Block a user