A powerful Lavalink library for Discord.py.

Overview

logo.png?raw=true

https://api.codacy.com/project/badge/Grade/d020ed97fd2a46fcb1f42bd3bc397e63

A robust and powerful Lavalink wrapper for Discord.py!

Documentation

Official Documentation.

Support

For support using WaveLink, please join the official support server on Discord.

Discord

Installation

The following commands are currently the valid ways of installing WaveLink.

WaveLink requires Python 3.7+

Windows

py -3.7 -m pip install Wavelink

Linux

python3.7 -m pip install Wavelink

Getting Started

A quick and easy bot example:

import discord
import wavelink
from discord.ext import commands


class Bot(commands.Bot):

    def __init__(self):
        super(Bot, self).__init__(command_prefix=['audio ', 'wave ','aw '])

        self.add_cog(Music(self))

    async def on_ready(self):
        print(f'Logged in as {self.user.name} | {self.user.id}')


class Music(commands.Cog):

    def __init__(self, bot):
        self.bot = bot

        if not hasattr(bot, 'wavelink'):
            self.bot.wavelink = wavelink.Client(bot=self.bot)

        self.bot.loop.create_task(self.start_nodes())

    async def start_nodes(self):
        await self.bot.wait_until_ready()

        # Initiate our nodes. For this example we will use one server.
        # Region should be a discord.py guild.region e.g sydney or us_central (Though this is not technically required)
        await self.bot.wavelink.initiate_node(host='127.0.0.1',
                                              port=2333,
                                              rest_uri='http://127.0.0.1:2333',
                                              password='youshallnotpass',
                                              identifier='TEST',
                                              region='us_central')

    @commands.command(name='connect')
    async def connect_(self, ctx, *, channel: discord.VoiceChannel=None):
        if not channel:
            try:
                channel = ctx.author.voice.channel
            except AttributeError:
                raise discord.DiscordException('No channel to join. Please either specify a valid channel or join one.')

        player = self.bot.wavelink.get_player(ctx.guild.id)
        await ctx.send(f'Connecting to **`{channel.name}`**')
        await player.connect(channel.id)

    @commands.command()
    async def play(self, ctx, *, query: str):
        tracks = await self.bot.wavelink.get_tracks(f'ytsearch:{query}')

        if not tracks:
            return await ctx.send('Could not find any songs with that query.')

        player = self.bot.wavelink.get_player(ctx.guild.id)
        if not player.is_connected:
            await ctx.invoke(self.connect_)

        await ctx.send(f'Added {str(tracks[0])} to the queue.')
        await player.play(tracks[0])


bot = Bot()
bot.run('TOKEN')
Comments
  • TypeError: 'coroutine' object is not callable

    TypeError: 'coroutine' object is not callable

    I'm getting this error when I try and play music on using my discord bot.

    Task exception was never retrieved future: <Task finished name='Task-32' coro=<Websocket.process_data() done, defined at C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py:137> exception=TypeError("'coroutine' object is not callable")> Traceback (most recent call last): File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py", line 156, in process_data event, payload = await self._get_event_payload(data['type'], data) File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py", line 184, in get_event_payload track = await self.node.build_track(cls=wavelink.Track, identifier=base64) File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\pool.py", line 294, in build_track return cls(identifier, data) TypeError: 'coroutine' object is not callable Task exception was never retrieved future: <Task finished name='Task-39' coro=<Websocket.process_data() done, defined at C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py:137> exception=TypeError("'coroutine' object is not callable")> Traceback (most recent call last): File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py", line 156, in process_data event, payload = await self._get_event_payload(data['type'], data) File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py", line 184, in get_event_payload track = await self.node.build_track(cls=wavelink.Track, identifier=base64) File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\pool.py", line 294, in build_track return cls(identifier, data) TypeError: 'coroutine' object is not callable

    Not a Bug 
    opened by Kaz213 15
  • Player.is_playing always returns False after track replace

    Player.is_playing always returns False after track replace

    Was broken in this commit: https://github.com/PythonistaGuild/Wavelink/commit/f126755662cdf17199b7814dbe4abcb5f038966b After first track has been replaced with Player.play(track), track_end event triggered after Player.play done. So, after first track replaced, Player._source is always None and Player.is_playing() always returns False.

    Consider changing code from commit above to something like this:

    if event == 'track_end' and payload.get('reason') == 'FINISHED':
        player._source = None
    
    opened by wladbelsky 7
  • Add support for

    Add support for "Session resuming" & "session data queueing".

    This PR is Implemented in #66

    Added New attributes

    • resume_session: bool
    • resume_timeout: float
    • resume_key: str (Best left None)
    • payload_timeout: float This is basically how recent requests shall be sent to the server
    • Websocket.reset() method.

    What are the new features?

    Websocket queueing.

    • Websocket._send() method now queues any data that is requested to be sent while the WS is disconnected.
    • New method Websocket.send_queue() which is called when connecting, and sends queue only when a session is resumed and Websocket is connected.
    • New exception NodeSessionClosedError raised when node closes a session or doesn't resume the old session. Handled within _connect method.

    Resuming

    • example of use of new features
    import string
    import secret
    class key:
        def __init__(self, len, first_key="NoSnoopingOnMyLava"):
            self.len = len
            self.persistent = first_key
    
        def __str__(self):
            return self.persistent
    
        def __repr__(self):
            """This should generate a key and shall make it persistent """
            self.persistent = SomeSecurePasswordGenerator(self.len)
            return self.persistent
    
    ---------------
    
     async def start_nodes(self) -> None:
        """Connect and intiate nodes."""
        nodes = {'MAIN': {'host': 'lavaserver.badhost.com',
                          'port': 80,
                          'rest_uri': 'http://lavaserver.badhost.com',
                          'password': "verytrivialpassword",
                          'identifier': 'MAIN',
                          'region': 'us_central',
                          'heartbeat': 40.0, # ping the server every 40s
                          'resume_session': True,
                          'resume_timeout': 90.0,
                          'resume_key': key(10) # or "Astring"
                          'payload_timeout': 40.0
                          }}
    
        for n in nodes.values():
            await self.bot.wavelink.initiate_node(**n)
    
    • or simply by setting 'resume_session': True
     async def start_nodes(self) -> None:
        """Connect and intiate nodes."""
        nodes = {'MAIN': {'host': 'lavaserver.badhost.com',
                          'port': 80,
                          'rest_uri': 'http://lavaserver.badhost.com',
                          'password': "verytrivialpassword",
                          'identifier': 'MAIN',
                          'region': 'us_central',
                          'resume_session': True
                          }}
    
        for n in nodes.values():
            await self.bot.wavelink.initiate_node(**n)
    

    Though the former has more use cases by using a Key Object we can:

    • Make the key persistent across Clusters
    • log the events, since __str__ is called when configuring the server, while __repr__ is called when the Node's session is closed to generate a new key.
    • To Generate a more secure password
    • Increase length of the password (The default is 32 characters)
    • Use

    How does resuming work?

    When the bot disconnects from the node (eg: 1006) then the lavalink server keeps on playing the music until session timeout, this allows the bot to reconnect and take control of the session. This PR implements this lavalink feature. The changes are not breaking, assuming no-one initializes Node instances directly.

    How does Queueing work?

    After the Node disconnects, we try to reconnect twice before timeout. during this time the requests to the node are queued in an asyncio.Queue subclass whose payload expires after some time. This could be useful when you have an higher timeout but want to only send recent requests

    opened by WizzyGeek 7
  • Add /decodetracks endpoint support

    Add /decodetracks endpoint support

    In addition to the Client/Node.build_track method, this adds the corresponding POST to /decodetracks to batch decode track identifiers. Useful if there are a large number of tracks that need to be decoded.

    The definition of the endpoint can be found here: https://github.com/Frederikam/Lavalink/blob/18ee6778674b7f9a817893b676a91a9b96e642f3/LavalinkServer/src/main/java/lavalink/server/player/AudioLoaderRestHandler.java#L140

    opened by james7132 6
  • AttributeError: '_MissingSentinel' object has no attribute 'guild'

    AttributeError: '_MissingSentinel' object has no attribute 'guild'

    Hi I am trying to make a setvolume command but I keep getting this error: AttributeError: '_MissingSentinel' object has no attribute 'guild'

    Code:

    @bot.command()
    async def setVolume(ctx, *, volume: float):
        vc = ctx.voice_client
        custom_player = CustomPlayer()
    
        if not vc:
            await ctx.send("I ain't in a vc bro")
        else:
            await custom_player.set_volume(volume=volume)
    opened by Necrosis000 5
  • Is there a better way to play a local file?

    Is there a better way to play a local file?

    I've finally got playing a local file (to lavalink) from the bot. (No more ffmpeg)

    I'm Just throwing this out here as a general question:

    is there a better way to search for a Local Track? I see SearchableTrack, having a return_first=true. Just trying to get my head around the API. Any help is apperciated?

    @slash_command(name="lplay", description="Play some local music or SFX") async def lplay(self, inter: Interaction, search): path = "/media/" + search
        search = wavelink.PartialTrack(query=path, cls=wavelink.LocalTrack)
    
        if inter.user.voice is None:
            return await inter.send(f'You are not connected to any voice channel!')
    
        # If the bot isn't in a voice channel
        if not inter.guild.voice_client:
            vc: wavelink.Player = await inter.user.voice.channel.connect(cls=wavelink.Player)
        else:
          #See if the bot is in another channel
          if inter.guild.voice_client.channel != inter.user.voice.channel:
            await inter.guild.voice_client.move_to(inter.user.voice.channel) 
            await inter.send(f'Connected to {inter.user.voice.channel}.')
            
        vc: wavelink.Player = inter.guild.voice_client
       
        try: 
           await vc.play(search)
           await inter.send(f'Playing {search.title}')
        except:
           await inter.send(f'{path} Not found!') 
    
    opened by Mudpuppy12 4
  • queue error please help

    queue error please help

    @bot.event async def on_wavelink_track_end(player: wavelink.Player, track: wavelink.Track, reason): ctx = player.ctx vc: player = ctx.voice_client if vc.loop: return await vc.play(track) next_song = vc.queue.get() await vc.play(next_song) await ctx.send(f"Now playing {next_song.title}")

    • File "/home/container/discord-bot/main.py", line 118, in on_wavelink_track_end next_song = vc.queue.get() File "/home/container/.local/lib/python3.10/site-packages/wavelink/queue.py", line 212, in get raise QueueEmpty("No items in the queue.") wavelink.errors.QueueEmpty: No items in the queue.
    opened by slefgameRz 4
  • wavelink.Player.connect incompatibility with Discord.py 2.0

    wavelink.Player.connect incompatibility with Discord.py 2.0

    Discord.py 2.0 introduced a new self_deaf and self_mute parameter to the connect method. This causes TypeError: Player.connect() got an unexpected keyword argument 'self_deaf'

    opened by Luc1412 4
  • module 'wavelink' has no attribute 'client'

    module 'wavelink' has no attribute 'client'

    Traceback (most recent call last): File "/Users/admin/Desktop/Cogs/music1.py", line 272, in bot = Bot() File "/Users/admin/Desktop/Cogs/music1.py", line 22, in init self.add_cog(Music(self)) File "/Users/admin/Desktop/Cogs/music1.py", line 69, in init self.bot.wavelink = wavelink.Client(bot=self.bot) AttributeError: module 'wavelink' has no attribute 'Client'

    opened by sanjaysanooj22 4
  • v1.2.0 No Longer Supports Python Version 3.8

    v1.2.0 No Longer Supports Python Version 3.8

    In the newest version (v1.2.0), the implementation of the YouTube Playlist searching has removed support for Python Version 3.8. The use of the method .removeprefix() is a python 3.9+ feature.

    The line in question: https://github.com/PythonistaGuild/Wavelink/blob/8a4fb12404a5e908bd7a22ecba1ace7dc950d73f/wavelink/tracks.py#L187

    PEP 616: String methods to remove prefixes and suffixes https://www.python.org/dev/peps/pep-0616/

    If this is intentional to remove Python 3.8 version, then please can the documentation be updated. Otherwise, an implementation to get around this could be:

    def removePrefix(url, prefix):
        if string.startswith(prefix):
            return string[len(prefix):]
        else:
            return string
    
    opened by TwoSails 4
  • [Suggestion] Advanced exmple

    [Suggestion] Advanced exmple

    Hello, Wavelink is working good but in my opinion there a a few missing things:

    • loop song & queue
    • lyrics command
    • pitch (1.00 standard 5.00 max)
    • option to keep the bot into the voicechannel even if nothing is playing.
    opened by FeelsBadMan1 4
  • Add payload_args optional argument to the play method in player.py

    Add payload_args optional argument to the play method in player.py

    This argument allows the user to pass arguments which will be directly sent to Lavalink in the play method. This gives the ability to interact with Lavalink plugins

    opened by Rajdave69 0
  • getting this error on 2.0

    getting this error on 2.0

    File "/home/subrata/Wavelink/wavelink/node.py", line 106, in <genexpr>
        version_tuple = tuple(int(v) for v in version.split('.'))
    ValueError: invalid literal for int() with base 10: 'c597fb10d9d323a174b69efa66fcebd616fb3f1e-SNAPSHOT_Unofficial'
    
    bug 2.0 
    opened by Subrata2402 0
  • Update pool.py

    Update pool.py

    Fixed bug with 'wavelink.NodePool.get_node(region="rotterdam")' raise ZeroConnectedNodes(f "No Nodes for region <{region}> exist on this pool."), although there is at least one node with this region.

    opened by Marco12223 1
  • Player running endless (without sound)

    Player running endless (without sound)

    I currently play an MP3 on the lavalink server in a loop. The loop has been accomplished by following code.

    @commands.Cog.listener(name="on_wavelink_track_end")
        async def _on_track_end(self, player: RadioPlayer, track: wavelink.Track, reason: str):
            if reason != 'FINISHED':
                return
            await player.play(track)
    

    This transition works fine so far. I also added on_wavelink_track_exception and on_wavelink_track_stuck for debug reasons, but both won't get triggered.

    I experience that the player randomly stops playing. The client is still connected. The player got is_connected() and is_playing() set to True. But when checking the position it got an inappropriate high number set.

    My track is about an hour long, but postion is set to 21h in seconds.

    Pausing and resuming resumes the playback.

    opened by Luc1412 0
  • cant search for youtube playlist

    cant search for youtube playlist

    I try to use wavelink.YouTubePlaylist to search for youtubeplaylist and I get error

    code @commands.command(aliases=['P', 'PLAY', 'Play','p']) async def play(self,ctx: commands.Context, *, search:wavelink.YouTubePlaylist): print(search)

    error Ignoring exception in on_message Traceback (most recent call last): File "C:\Python3.10\lib\site-packages\discord\ext\commands\core.py", line 456, in _actual_conversion ret = await method(ctx, argument) File "C:\Python3.10\lib\site-packages\wavelink\tracks.py", line 218, in convert return results[0] TypeError: 'YouTubePlaylist' object is not subscriptable

    Did i miss something?

    and also sorry for my bad English

    opened by tunwit 2
Releases(v1.3.4)
  • v1.3.4(Dec 22, 2022)

  • v1.3.3(Oct 4, 2022)

  • v1.3.2(Jul 10, 2022)

  • v1.3.1(Jun 6, 2022)

  • v1.3.0(Jun 6, 2022)

    Implemented Lavalink Filters, some documentation can be found here: https://wavelink.readthedocs.io/en/latest/wavelink.html#filters This is still a WIP.

    Fixed an issue with YouTubePlaylist converter failing. Bumped aiohttp inline with discord.py

    Source code(tar.gz)
    Source code(zip)
  • v1.2.5(Apr 22, 2022)

  • v1.2.4(Mar 21, 2022)

  • v1.2.3(Mar 21, 2022)

  • v1.2.2(Mar 13, 2022)

  • v1.2.1(Mar 10, 2022)

  • v1.2.0(Mar 7, 2022)

  • v1.1.1(Feb 8, 2022)

  • v1.1.0(Feb 4, 2022)

  • v1.0.2(Jan 24, 2022)

  • v1.0.1(Jan 24, 2022)

  • v1.0.0(Jan 24, 2022)

    Wavelink 1.0.0

    This release is a whole rewrite of the library. It supports discord.py 2.0 and some derivatives.

    See the documentaion for more info and examples. Documentation

    If the documentation is still displaying as the old version, please clear your cache.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.10(Jul 13, 2021)

  • v0.9.9(Mar 8, 2021)

  • v0.9.8(Feb 25, 2021)

    Add force keyword argument to Node.destroy() and Player.destroy()/disconnect(). This prevents a bug from occuring when a player is being destroyed, and the bot is no longer apart of the Guild the player was associated with.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.7(Feb 23, 2021)

  • v0.9.6(Sep 9, 2020)

    Fix a bug in player setting current track to None on TrackStuck and TrackException.

    Since Lavalink sends two events on Exceptions, an End and Exception event this causes a possible race condition in the player, setting the current Track to None when one is actually playing.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.5(Sep 5, 2020)

    Added Exponential Backoff attempts to get_tracks. Retrieving tracks will now by default retry on failure up to a maximum of 5 attempts with an Exponential Backoff. You can set this to False with the kwarg retry_on_failure=False, which will only attempt to retrieve tracks once.

    Added support for custom JSON Encoders.

    Changed YouTube's Track Image to hqdefault, in place of maxresdefault.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.4(Aug 5, 2020)

    Changes to Equalizer which allow for construction without the build() classmethod.

    Added name parameters to the build() classmethod and Equalizer constructor to allow setting a custom name.

    Added a name property to Equalizer. Setting the name should be done by constrcutor or the build() classmethod

    Added __str__ and __repr__ to Equalizer.

    Fixed a bug where set_eq was setting a blank Equalizer class on the player.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.3(Jul 30, 2020)

  • v0.9.2(Jun 20, 2020)

    Add heartbeat to node and websocket.

    This stabilizes connection to Nodes hosted on a VPS with a router or any such intermediate process that closes the connection if it remains idle. Which puts the bot in a "reconnection" loop.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.1(Jun 20, 2020)

  • v0.9.0(Jun 8, 2020)

    Added wavelink.WavelinkMixin to be used in conjunction with a discord.py commands.Cog. This class allows for the registration of the new wavelink listeners:

    on_node_ready on_track_start on_track_end on_track_stuck on_track_exception on_websocket_closed

    All listeners must be decorated with the wavelink.WavelinkMixin.listener() decorator. All listeners must be in a wavelink.WavelinkMixin class. Listeners can be stacked.

    Docs

    Event Payloads WavelinkMixin

    Example

    class Music(commands.Cog, wavelink.WavelinkMixin):
        
        @wavelink.WavelinkMixin.listener()
        async def on_node_ready(self, node):
            print(f'Node {node.identifier} is ready!')
    
    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(May 18, 2020)

  • v0.7.2(May 16, 2020)

  • v0.7.1(May 2, 2020)

Owner
Pythonista
Organisation for the Pythonista Guild
Pythonista
🤖 Telegram UserBot Untuk Memutar Lagu Dan Video Di Obrolan Suara Telegram.

🤖 Telegram UserBot Untuk Memutar Lagu Dan Video Di Obrolan Suara Telegram.

Fariz 2 Nov 13, 2021
Multi-Branch CI/CD Pipeline using CDK Pipelines.

Using AWS CDK Pipelines and AWS Lambda for multi-branch pipeline management and infrastructure deployment. This project shows how to use the AWS CDK P

AWS Samples 36 Dec 23, 2022
A Python Program to determine Degree of Profanity of Tweets

tweetx tweetx is a program to detect racial slurs in Twitter Tweets. Racial Abuse on Twitter is becoming quite a serious issue in recent times. tweetx

Kartik Poojari 3 Nov 11, 2021
可基于【腾讯云函数】/【GitHub Actions】/【Docker】的每日签到脚本(支持多账号使用)签到列表: |爱奇艺|全民K歌|腾讯视频|有道云笔记|网易云音乐|一加手机社区官方论坛|百度贴吧|Bilibili|V2EX|咔叽网单|什么值得买|AcFun|天翼云盘|WPS|吾爱破解|芒果TV|联通营业厅|Fa米家|小米运动|百度搜索资源平台|每日天气预报|每日一句|哔咔漫画|和彩云|智友邦|微博|CSDN|王者营地|

每日签到集合 基于【腾讯云函数】/【GitHub Actions】/【Docker】的每日签到脚本 支持多账号使用 特别声明: 本仓库发布的脚本及其中涉及的任何解锁和解密分析脚本,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。

87 Nov 12, 2022
Client to allow skytrack to be used with GSPro Golf simulator application

Skytrack Interface for GSPro A Basic Interface connection from Skytrack Launch Monitors to be able to play simulator golf via GSPro About The Project

James Peruggia 2 Oct 24, 2021
This code will guide you on how you can make your own Twitter Bot.

This code will guide you on how you can make your own Twitter Bot. This bot retweets, and likes to tweet with a particular word, here Python3.

Kunal Diwan 1 Oct 14, 2022
LoL 台版10周年活動自動輸入邀請碼

LoLTW_10Year_88Event LoLTW 8.8 周年慶 邀請碼自動輸入 設定 在 LoLTW_10Year_88Evnet.exe 的位置建立一個檔案 .env,內容如下 Bahamut_Discussion = https://forum.gamer.com.tw/C.php?bsn

古丁丁 5 Dec 13, 2021
ARKHAM X GOD MULTISPAM BOT

ARKHAM-X-GOD-MULTISPAM-BOT 𝗗𝗘𝗣𝗟𝗢𝗬 𝗨𝗣𝗧𝗢 30 𝗕𝗢𝗧𝗦 𝗜𝗡 𝗔 𝗦𝗜𝗡𝗚𝗟?

ArkhamXGod 2 Jan 08, 2022
domhttpx is a google search engine dorker with HTTP toolkit built with python, can make it easier for you to find many URLs/IPs at once with fast time.

domhttpx is a google search engine dorker with HTTP toolkit built with python, can make it easier for you to find many URLs/IPs at once with fast time

Naufal Ardhani 59 Dec 04, 2022
Hasan Can Kaya - Konusanlar Ticket Notifier

Hasan Can Kaya - Konusanlar Ticket Notifier This script sends a notification to any telegram chat/group/channel when added a new available ticket to b

omer citak 3 Jan 31, 2022
Hcl.py is an Amino client for Python

Hcl.py Hcl.py Hcl.py is an Amino client for Python. It provides to access aminoapps Web, app and socket servers. Developed BY Kapidev And Upgraded BY

Oustex 3 Dec 02, 2021
A heraldry-related bot, designed for the Heraldry Community.

Heraldtron A heraldry-related bot, designed for the Heraldry Community. Requirements Python 3.9+ discord.py aiohttp (comes installed with discord.py)

1 Mar 31, 2022
HinamiRobot - Telegram Group Manager Bot Written In Python Using Pyrogram

✨ HINAMI CHAN ✨ Telegram Group Manager Bot Written In Python Using Pyrogram. Rea

DARK LEGEND088 2 Jan 27, 2022
The Python version of the official Discord bot for the Astura Studios Discord community server.

About Astura (Python version) is the official Discord bot for the Astura Studios Discord community server developed and maintained by Ascendus and the

Ascendus 1 Apr 21, 2022
An interactive and multi-function Telegram bot, made especially for Telegram groups.

PyKorone An interaction and fun bot for Telegram groups, having some useful and other useless commands. Created as an experiment and learning bot but

Amano Team 17 Nov 12, 2022
TypeRig is a Python library aimed at simplifying the current FontLab API

TypeRig TypeRig is a Python library aimed at simplifying the current FontLab API while offering some additional functionality that is heavily biased t

Vassil Kateliev 41 Nov 02, 2022
Fastest Tiktok Username checker on site.

Tiktok Username Checker Fastest Tiktok Username checker on site

sql 3 Jun 19, 2021
Skyscanner Python SDK

Skyscanner Python SDK Important As of May 1st, 2020, the project is deprecated and no longer maintained. The latest update in v1.1.5 includes changing

Skyscanner 118 Sep 23, 2022
Home Assistant custom integration for controlling Powered by Tuya (PBT) devices using Tuya Open API, officially maintained by the Tuya Developer Team.

Tuya Home Assistant Integration Home Assistant custom integration for controlling Powered by Tuya (PBT) devices using Tuya Open API, officially mainta

Tuya 704 Jan 03, 2023
A library that allows you to easily mock out tests based on AWS infrastructure.

Moto - Mock AWS Services Install $ pip install moto[ec2,s3,all] In a nutshell Moto is a library that allows your tests to easily mock out AWS Services

Steve Pulec 6.5k Jan 02, 2023