├── requirements.txt ├── setup.py ├── LICENSE ├── README.md ├── .gitignore └── jeyyapi └── __init__.py /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open('README.md') as f: 4 | long_description = f.read() 5 | 6 | with open('requirements.txt') as f: 7 | requirements = f.read().splitlines() 8 | 9 | setuptools.setup( 10 | name='jeyyapi', 11 | version='1.1', 12 | description='Python wrapper for JeyyAPI', 13 | long_description=long_description, 14 | url='http://github.com/JeyyGit/jeyyapi', 15 | author='JeyyGit', 16 | license='MIT', 17 | packages=['jeyyapi'], 18 | install_requires=['aiohttp'], 19 | requirements=requirements 20 | ) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 JeyyGit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jeyyapi (async) 2 | Async python wrapper for [JeyyAPI](https://api.jeyy.xyz) 3 | 4 | # Installation 5 | ```bash 6 | $ pip install git+https://github.com/JeyyGit/jeyyapi.git 7 | ``` 8 | 9 | # Example usage 10 | ```py 11 | # import JeyyAPIClient 12 | from jeyyapi import JeyyAPIClient 13 | 14 | # Create JeyyAPICLient instance 15 | client = JeyyAPIClient('YOUR_API_KEY_HERE') 16 | 17 | # fetch from `hearts` endpoint with its appropriate kwargs parameter 18 | # returns io.BytesIO for image and discord endpoints 19 | image = await client.hearts(image_url='IMAGE_URL', rainbow=True) 20 | ``` 21 | 22 | ### spotify command example on discord.py (2.0) 23 | ```py 24 | from jeyyapi import JeyyAPIClient 25 | 26 | client = JeyyAPIClient('YOUR_API_KEY_HERE') 27 | 28 | # requires presence intent 29 | @bot.command() 30 | async def spotify(ctx, member: discord.Member=None): 31 | member = member or ctx.author 32 | spotify = discord.utils.find(lambda a: isinstance(a, discord.Spotify), member.activities) 33 | 34 | if spotify is None: 35 | return await ctx.send(f"**{member}** is not listening or connected to Spotify.") 36 | 37 | image = await client.spotify_from_object(spotify) 38 | 39 | await ctx.send(f"> **{member}** is listening to **{spotify.title}**", file=discord.File(image, 'spotify.png')) 40 | ``` 41 | 42 | #### Close the client session with `await client.close()` if you didn't pass your own session 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /jeyyapi/__init__.py: -------------------------------------------------------------------------------- 1 | import aiohttp 2 | from aiohttp import FormData 3 | import typing 4 | import yarl 5 | import datetime 6 | from io import BytesIO 7 | 8 | try: 9 | import discord 10 | except ImportError: 11 | pass 12 | 13 | 14 | class APIError(Exception): 15 | pass 16 | 17 | 18 | class JeyyAPIClient: 19 | def __init__(self, api_key: str, *, session: typing.Optional[aiohttp.ClientSession] = None) -> None: 20 | self.base_url: yarl.URL = yarl.URL('https://api.jeyy.xyz/v2/') 21 | self.headers = {'Authorization': f'Bearer {api_key}'} 22 | self.new_session = False 23 | if session is None: 24 | self.session = aiohttp.ClientSession() 25 | self.new_session = True 26 | else: 27 | self.session = session 28 | 29 | async def close(self) -> None: 30 | if self.new_session: 31 | if self.session.closed: 32 | raise TypeError('session is already closed') 33 | 34 | await self.session.close() 35 | else: 36 | raise TypeError('session was created manually. call .close() on the session instead.') 37 | 38 | async def __aenter__(self): 39 | if self.session.closed: 40 | raise TypeError('session has closed') 41 | 42 | return self 43 | 44 | async def __aexit__(self, exc_type, exc, tb): 45 | try: 46 | await self.close() 47 | except: 48 | pass 49 | 50 | # general 51 | async def ping(self): 52 | async with self.session.get(self.base_url / 'general/ping', headers=self.headers) as resp: 53 | if resp.status != 200: 54 | raise APIError(await resp.text()) 55 | 56 | result = await resp.json() 57 | return result 58 | 59 | async def endpoints(self): 60 | async with self.session.get(self.base_url / 'general/endpoints', headers=self.headers) as resp: 61 | if resp.status != 200: 62 | raise APIError(await resp.text()) 63 | 64 | result = await resp.json() 65 | return result 66 | 67 | async def image_upload(self, image: bytes): 68 | formdata = FormData() 69 | formdata.add_field('image', BytesIO(image), content_type='image/gif') 70 | async with self.session.post(self.base_url / 'general/image_upload', data=formdata, headers=self.headers) as resp: 71 | if resp.status != 200: 72 | raise APIError(await resp.text()) 73 | 74 | result = await resp.json() 75 | 76 | return result 77 | 78 | async def plat_nomor(self, plat: str): 79 | async with self.session.get(self.base_url / 'general/plat_nomor', params={'plat': plat}, headers=self.headers) as resp: 80 | if resp.status != 200: 81 | raise APIError(await resp.text()) 82 | 83 | result = await resp.json() 84 | 85 | return result 86 | 87 | # image 88 | async def _image_fetch(self, endpoint, **params) -> BytesIO: 89 | url = self.base_url / f'image/{endpoint}' 90 | async with self.session.get(url, params=params, headers=self.headers) as resp: 91 | if resp.status != 200: 92 | raise APIError(await resp.text()) 93 | 94 | data = await resp.read() 95 | 96 | buffer = BytesIO(data) 97 | return buffer 98 | 99 | async def bevel(self, image_url: str, level: typing.Optional[int] = 15) -> BytesIO: 100 | return await self._image_fetch('bevel', image_url=str(image_url), level=int(level)) 101 | 102 | async def patpat(self, image_url: str) -> BytesIO: 103 | return await self._image_fetch('patpat', image_url=str(image_url)) 104 | 105 | async def burn(self, image_url: str) -> BytesIO: 106 | return await self._image_fetch('burn', image_url=str(image_url)) 107 | 108 | async def glitch(self, image_url: str, level: typing.Optional[int] = 3) -> BytesIO: 109 | return await self._image_fetch('glitch', image_url=str(image_url), level=int(level)) 110 | 111 | async def boil(self, image_url: str, level: typing.Optional[str] = 2) -> BytesIO: 112 | return await self._image_fetch('boil', image_url=str(image_url), level=int(level)) 113 | 114 | async def earthquake(self, image_url: str, level: typing.Optional[int] = 3) -> BytesIO: 115 | return await self._image_fetch('earthquake', image_url=str(image_url), level=int(level)) 116 | 117 | async def hearts(self, image_url: str, rainbow: typing.Optional[bool] = True) -> BytesIO: 118 | return await self._image_fetch('hearts', image_url=str(image_url), rainbow=str(bool(rainbow))) 119 | 120 | async def shock(self, image_url: str) -> BytesIO: 121 | return await self._image_fetch('shock', image_url=str(image_url)) 122 | 123 | async def abstract(self, image_url: str) -> BytesIO: 124 | return await self._image_fetch('abstract', image_url=str(image_url)) 125 | 126 | async def infinity(self, image_url: str) -> BytesIO: 127 | return await self._image_fetch('infinity', image_url=str(image_url)) 128 | 129 | async def bomb(self, image_url: str) -> BytesIO: 130 | return await self._image_fetch('bomb', image_url=str(image_url)) 131 | 132 | async def bonks(self, image_url: str) -> BytesIO: 133 | return await self._image_fetch('bonks', image_url=str(image_url)) 134 | 135 | async def sob(self, image_url: str) -> BytesIO: 136 | return await self._image_fetch('sob', image_url=str(image_url)) 137 | 138 | async def explicit(self, image_url: str) -> BytesIO: 139 | return await self._image_fetch('explicit', image_url=str(image_url)) 140 | 141 | async def blur(self, image_url: str) -> BytesIO: 142 | return await self._image_fetch('blur', image_url=str(image_url)) 143 | 144 | async def lamp(self, image_url: str) -> BytesIO: 145 | return await self._image_fetch('lamp', image_url=str(image_url)) 146 | 147 | async def rain(self, image_url: str) -> BytesIO: 148 | return await self._image_fetch('rain', image_url=str(image_url)) 149 | 150 | async def canny(self, image_url: str) -> BytesIO: 151 | return await self._image_fetch('canny', image_url=str(image_url)) 152 | 153 | async def cartoon(self, image_url: str) -> BytesIO: 154 | return await self._image_fetch('cartoon', image_url=str(image_url)) 155 | 156 | async def layers(self, image_url: str) -> BytesIO: 157 | return await self._image_fetch('layers', image_url=str(image_url)) 158 | 159 | async def radiate(self, image_url: str) -> BytesIO: 160 | return await self._image_fetch('radiate', image_url=str(image_url)) 161 | 162 | async def shoot(self, image_url: str) -> BytesIO: 163 | return await self._image_fetch('shoot', image_url=str(image_url)) 164 | 165 | async def tv(self, image_url: str) -> BytesIO: 166 | return await self._image_fetch('tv', image_url=str(image_url)) 167 | 168 | async def shear(self, image_url: str, axis: typing.Optional[str] = 'X') -> BytesIO: 169 | return await self._image_fetch('shear', image_url=str(image_url), axis=str(axis)) 170 | 171 | async def magnify(self, image_url: str) -> BytesIO: 172 | return await self._image_fetch('magnify', image_url=str(image_url)) 173 | 174 | async def print(self, image_url: str) -> BytesIO: 175 | return await self._image_fetch('print', image_url=str(image_url)) 176 | 177 | async def matrix(self, image_url: str) -> BytesIO: 178 | return await self._image_fetch('matrix', image_url=str(image_url)) 179 | 180 | async def sensitive(self, image_url: str) -> BytesIO: 181 | return await self._image_fetch('sensitive', image_url=str(image_url)) 182 | 183 | async def dilute(self, image_url: str) -> BytesIO: 184 | return await self._image_fetch('dilute', image_url=str(image_url)) 185 | 186 | async def dither(self, image_url: str) -> BytesIO: 187 | return await self._image_fetch('dither', image_url=str(image_url)) 188 | 189 | async def pattern(self, image_url: str) -> BytesIO: 190 | return await self._image_fetch('pattern', image_url=str(image_url)) 191 | 192 | async def logoff(self, image_url: str) -> BytesIO: 193 | return await self._image_fetch('logoff', image_url=str(image_url)) 194 | 195 | async def dilate(self, image_url: str) -> BytesIO: 196 | return await self._image_fetch('dilate', image_url=str(image_url)) 197 | 198 | async def fire(self, image_url: str) -> BytesIO: 199 | return await self._image_fetch('fire', image_url=str(image_url)) 200 | 201 | async def fall(self, image_url: str) -> BytesIO: 202 | return await self._image_fetch('fall', image_url=str(image_url)) 203 | 204 | async def fan(self, image_url: str) -> BytesIO: 205 | return await self._image_fetch('fan', image_url=str(image_url)) 206 | 207 | async def flag(self, image_url: str) -> BytesIO: 208 | return await self._image_fetch('flag', image_url=str(image_url)) 209 | 210 | async def melt(self, image_url: str) -> BytesIO: 211 | return await self._image_fetch('melt', image_url=str(image_url)) 212 | 213 | async def contour(self, image_url: str, rainbow: bool = False) -> BytesIO: 214 | return await self._image_fetch('contour', image_url=str(image_url), rainbow=rainbow) 215 | 216 | async def cracks(self, image_url: str) -> BytesIO: 217 | return await self._image_fetch('cracks', image_url=str(image_url)) 218 | 219 | async def im_emojify(self, image_url: str, size: int = 32) -> BytesIO: 220 | return await self._image_fetch('emojify', image_url=str(image_url), size=size) 221 | 222 | async def endless(self, image_url: str) -> BytesIO: 223 | return await self._image_fetch('endless', image_url=str(image_url)) 224 | 225 | async def bayer(self, image_url: str) -> BytesIO: 226 | return await self._image_fetch('bayer', image_url=str(image_url)) 227 | 228 | async def slice(self, image_url: str) -> BytesIO: 229 | return await self._image_fetch('slice', image_url=str(image_url)) 230 | 231 | async def spikes(self, image_url: str) -> BytesIO: 232 | return await self._image_fetch('spikes', image_url=str(image_url)) 233 | 234 | async def blocks(self, image_url: str) -> BytesIO: 235 | return await self._image_fetch('blocks', image_url=str(image_url)) 236 | 237 | async def phone(self, image_url: str) -> BytesIO: 238 | return await self._image_fetch('phone', image_url=str(image_url)) 239 | 240 | async def laundry(self, image_url: str) -> BytesIO: 241 | return await self._image_fetch('laundry', image_url=str(image_url)) 242 | 243 | async def pizza(self, image_url: str) -> BytesIO: 244 | return await self._image_fetch('pizza', image_url=str(image_url)) 245 | 246 | async def ripped(self, image_url: str) -> BytesIO: 247 | return await self._image_fetch('ripped', image_url=str(image_url)) 248 | 249 | async def cinema(self, image_url: str) -> BytesIO: 250 | return await self._image_fetch('cinema', image_url=str(image_url)) 251 | 252 | async def stretch(self, image_url: str) -> BytesIO: 253 | return await self._image_fetch('stretch', image_url=str(image_url)) 254 | 255 | async def dots(self, image_url: str) -> BytesIO: 256 | return await self._image_fetch('dots', image_url=str(image_url)) 257 | 258 | async def tunnel(self, image_url: str, direction: typing.Literal['h', 'horizontal', 'v', 'vertical', 'c', 'circle', 'r', 'rotate']) -> BytesIO: 259 | return await self._image_fetch('tunnel', image_url=str(image_url), direction=direction) 260 | 261 | async def zonk(self, image_url: str) -> BytesIO: 262 | return await self._image_fetch('zonk', image_url=str(image_url)) 263 | 264 | async def knit(self, image_url: str) -> BytesIO: 265 | return await self._image_fetch('knit', image_url=str(image_url)) 266 | 267 | async def plank(self, image_url: str) -> BytesIO: 268 | return await self._image_fetch('plank', image_url=str(image_url)) 269 | 270 | async def shred(self, image_url: str) -> BytesIO: 271 | return await self._image_fetch('shred', image_url=str(image_url)) 272 | 273 | async def liquefy(self, image_url: str) -> BytesIO: 274 | return await self._image_fetch('liquefy', image_url=str(image_url)) 275 | 276 | async def poly(self, image_url: str) -> BytesIO: 277 | return await self._image_fetch('poly', image_url=str(image_url)) 278 | 279 | async def spin(self, image_url: str) -> BytesIO: 280 | return await self._image_fetch('spin', image_url=str(image_url)) 281 | 282 | async def plates(self, image_url: str) -> BytesIO: 283 | return await self._image_fetch('plates', image_url=str(image_url)) 284 | 285 | async def lsd(self, image_url: str) -> BytesIO: 286 | return await self._image_fetch('lsd', image_url=str(image_url)) 287 | 288 | async def lines(self, image_url: str) -> BytesIO: 289 | return await self._image_fetch('lines', image_url=str(image_url)) 290 | 291 | async def ipcam(self, image_url: str) -> BytesIO: 292 | return await self._image_fetch('ipcam', image_url=str(image_url)) 293 | 294 | async def reflection(self, image_url: str) -> BytesIO: 295 | return await self._image_fetch('reflection', image_url=str(image_url)) 296 | 297 | async def stereo(self, image_url: str) -> BytesIO: 298 | return await self._image_fetch('stereo', image_url=str(image_url)) 299 | 300 | async def kanye(self, image_url: str) -> BytesIO: 301 | return await self._image_fetch('kanye', image_url=str(image_url)) 302 | 303 | async def letters(self, image_url: str) -> BytesIO: 304 | return await self._image_fetch('letters', image_url=str(image_url)) 305 | 306 | async def wiggle(self, image_url: str) -> BytesIO: 307 | return await self._image_fetch('wiggle', image_url=str(image_url)) 308 | 309 | async def tiles(self, image_url: str, n_edges: typing.Literal[3, 4, 5, 6, 7, 8] = 4) -> BytesIO: 310 | return await self._image_fetch('tiles', image_url=str(image_url), n_edges=n_edges) 311 | 312 | async def gameboy_camera(self, image_url: str) -> BytesIO: 313 | return await self._image_fetch('gameboy_camera', image_url=str(image_url)) 314 | 315 | async def ripple(self, image_url: str) -> BytesIO: 316 | return await self._image_fetch('ripple', image_url=str(image_url)) 317 | 318 | async def globe(self, image_url: str) -> BytesIO: 319 | return await self._image_fetch('globe', image_url=str(image_url)) 320 | 321 | async def cow(self, image_url: str) -> BytesIO: 322 | return await self._image_fetch('cow', image_url=str(image_url)) 323 | 324 | async def pyramid(self, image_url: str) -> BytesIO: 325 | return await self._image_fetch('pyramid', image_url=str(image_url)) 326 | 327 | async def wall(self, image_url: str) -> BytesIO: 328 | return await self._image_fetch('wall', image_url=str(image_url)) 329 | 330 | async def cube(self, image_url: str) -> BytesIO: 331 | return await self._image_fetch('cube', image_url=str(image_url)) 332 | 333 | async def paint(self, image_url: str) -> BytesIO: 334 | return await self._image_fetch('paint', image_url=str(image_url)) 335 | 336 | async def painting(self, image_url: str) -> BytesIO: 337 | return await self._image_fetch('painting', image_url=str(image_url)) 338 | 339 | async def shine(self, image_url: str) -> BytesIO: 340 | return await self._image_fetch('shine', image_url=str(image_url)) 341 | 342 | async def neon(self, image_url: str) -> BytesIO: 343 | return await self._image_fetch('neon', image_url=str(image_url)) 344 | 345 | async def flush(self, image_url: str) -> BytesIO: 346 | return await self._image_fetch('flush', image_url=str(image_url)) 347 | 348 | async def ace(self, name: str, side: typing.Literal['attorney', 'prosecutor'], text: str) -> BytesIO: 349 | return await self._image_fetch('ace', name=str(name), side=str(side), text=str(text)) 350 | 351 | async def gallery(self, image_url: str) -> BytesIO: 352 | return await self._image_fetch('gallery', image_url=str(image_url)) 353 | 354 | async def paparazzi(self, image_url: str) -> BytesIO: 355 | return await self._image_fetch('paparazzi', image_url=str(image_url)) 356 | 357 | async def balls(self, image_url: str) -> BytesIO: 358 | return await self._image_fetch('balls', image_url=str(image_url)) 359 | 360 | async def equation(self, image_url: str) -> BytesIO: 361 | return await self._image_fetch('equation', image_url=str(image_url)) 362 | 363 | async def half_invert(self, image_url: str) -> BytesIO: 364 | return await self._image_fetch('half_invert', image_url=str(image_url)) 365 | 366 | async def heart_locket(self, image_url: str, image_url_2: str = None) -> BytesIO: 367 | return await self._image_fetch('heart_locket', image_url=str(image_url), image_url_2=str(image_url_2) if image_url_2 else image_url_2) 368 | 369 | async def roll(self, image_url: str) -> BytesIO: 370 | return await self._image_fetch('roll', image_url=str(image_url)) 371 | 372 | async def wave(self, image_url: str, frequency: float = 0.05, amplitude: typing.Literal[1, 2, 3, 4, 5] = 1) -> BytesIO: 373 | return await self._image_fetch('wave', image_url=str(image_url), frequency=frequency, amplitude=amplitude) 374 | 375 | async def clock(self, image_url: str) -> BytesIO: 376 | return await self._image_fetch('clock', image_url=str(image_url)) 377 | 378 | async def optics(self, image_url: str) -> BytesIO: 379 | return await self._image_fetch('optics', image_url=str(image_url)) 380 | 381 | async def warp(self, image_url: str) -> BytesIO: 382 | return await self._image_fetch('warp', image_url=str(image_url)) 383 | 384 | async def ads(self, image_url: str) -> BytesIO: 385 | return await self._image_fetch('ads', image_url=str(image_url)) 386 | 387 | async def billboard(self, image_url) -> BytesIO: 388 | return await self._image_fetch('billboard', image_url=str(image_url)) 389 | 390 | async def bubble(self, image_url: str) -> BytesIO: 391 | return await self._image_fetch('bubble', image_url=str(image_url)) 392 | 393 | async def cloth(self, image_url: str) -> BytesIO: 394 | return await self._image_fetch('cloth', image_url=str(image_url)) 395 | 396 | async def youtube(self, avatar_url: str, author: str, title: str) -> BytesIO: 397 | return await self._image_fetch('youtube', avatar_url=str(avatar_url), author=str(author), title=str(title)) 398 | 399 | async def scrapbook(self, text: str) -> BytesIO: 400 | return await self._image_fetch('scrapbook', text=str(text)) 401 | 402 | # text 403 | async def emojify(self, image_url: str) -> dict: 404 | params = {'image_url': str(image_url)} 405 | async with self.session.get(self.base_url / 'text/emojify', params=params, headers=self.headers) as resp: 406 | if resp.status != 200: 407 | raise APIError(await resp.text()) 408 | 409 | result = await resp.json() 410 | 411 | return result 412 | 413 | # discord 414 | async def spotify(self, title: str, cover_url: str, duration: typing.Union[datetime.timedelta, int, float], start: typing.Union[datetime.datetime, float], artists: typing.List[str]) -> BytesIO: 415 | if isinstance(duration, datetime.timedelta): 416 | duration = int(duration.seconds) 417 | else: 418 | duration = int(duration) 419 | 420 | if isinstance(start, datetime.datetime): 421 | start = float(start.timestamp()) 422 | else: 423 | start = float(start) 424 | 425 | params = { 426 | 'title': str(title), 427 | 'cover_url': str(cover_url), 428 | 'duration_seconds': duration, 429 | 'start_timestamp': start, 430 | 'artists': artists 431 | } 432 | 433 | async with self.session.get(self.base_url / 'discord/spotify', params=params, headers=self.headers) as resp: 434 | if resp.status != 200: 435 | raise APIError(await resp.text()) 436 | 437 | data = await resp.read() 438 | 439 | buffer = BytesIO(data) 440 | return buffer 441 | 442 | async def spotify_from_object(self, spotify: discord.Spotify) -> BytesIO: 443 | if spotify.__class__.__name__ != 'Spotify': 444 | raise TypeError(f'discord.Spotify is expected, {spotify.__class__.__name__} is passed instead.') 445 | 446 | kwargs = { 447 | 'title': spotify.title, 448 | 'cover_url': spotify.album_cover_url, 449 | 'duration': spotify.duration.seconds, 450 | 'start': spotify.start.timestamp(), 451 | 'artists': spotify.artists 452 | } 453 | 454 | return await self.spotify(**kwargs) 455 | 456 | async def player(self, title: str, thumbnail_url: str, seconds_played: float, total_seconds: float, line_1: typing.Optional[str], line_2: typing.Optional[str]): 457 | params = { 458 | 'title': title, 459 | 'thumbnail_url': thumbnail_url, 460 | 'seconds_played': seconds_played, 461 | 'total_seconds': total_seconds, 462 | 'line_1': line_1, 463 | 'line_2': line_2, 464 | } 465 | 466 | async with self.session.get(self.base_url / 'discord/player', params=params, headers=self.headers) as resp: 467 | if resp.status != 200: 468 | raise APIError(await resp.text()) 469 | 470 | data = await resp.read() 471 | 472 | buffer = BytesIO(data) 473 | return buffer 474 | 475 | async def wheel(self, args: typing.Union[typing.List[str], typing.Tuple[str]]) -> dict: 476 | async with self.session.get(self.base_url / 'discord/wheel', params={'args': args}, headers=self.headers) as resp: 477 | if resp.status != 200: 478 | raise APIError(await resp.text()) 479 | 480 | result = await resp.json() 481 | 482 | return result 483 | 484 | async def ansi( 485 | self, 486 | text: str, 487 | bold: bool = False, 488 | underline: bool = False, 489 | text_color: typing.Literal['gray', 'red', 'green', 'yellow', 'blue', 'pink', 'cyan', 'white'] = None, 490 | bg_color: typing.Literal['dark blue', 'orange', 'gray 1', 'gray 2', 'gray 3', 'gray 4', 'indigo', 'white'] = None, 491 | codeblock: bool = True 492 | ) -> str: 493 | 494 | params = { 495 | 'text': text, 496 | 'bold': str(bold), 497 | 'underline': str(underline), 498 | 'text_color': text_color, 499 | 'bg_color': bg_color, 500 | 'codeblock': str(codeblock), 501 | } 502 | 503 | async with self.session.get(self.base_url / 'discord/ansi', params=params, headers=self.headers) as resp: 504 | if resp.status != 200: 505 | raise APIError(await resp.text()) 506 | 507 | result = await resp.json() 508 | 509 | return result 510 | 511 | 512 | --------------------------------------------------------------------------------