chatclicks


Namechatclicks JSON
Version 0.3.5 PyPI version JSON
download
home_pagehttps://github.com/WillPiledriver/chatclicks
SummaryA client for the Twitch Extension named Chat Clicks
upload_time2023-10-19 22:58:26
maintainer
docs_urlNone
authorWillPiledriver
requires_python>=3.5
licenseMIT
keywords twitch extension client chat
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # chatclicks
Python package for the Twitch extension "Chat Clicks"

## Installation
```pip install chatclicks```

## Setup
This is relatively simple to setup. Using the example below, you can really just do whatever you want with it. I will explain the main features. 

The main idea is to allow chat to essentially "vote" on clicks. This is done by waiting an arbitrary amount of time (polling time) to collect clicks from viewers. The program then uses math that I do not understand to find the center of the most dense cluster of clicks, and then send that data over to your code. I decided not to add code that handles clicking for the simple reason that there are many different packages that do this (pyautogui, pydirectinput, etc) and they each have their own use cases so I leave that up to you. The example below uses the package pydirectinput-rgx which i recommend to use for it's compatibility with modern games.

The extension does support bits. There are three different bits products: Chaos, Order, and Priority Clicks. Chaos reduces the polling time, and order increases the polling time. Priority Clicks gives the user's clicks more weight for their next X clicks, as defined by you. Be sure to define the bits cost in your program if you don't want people to cheat (there is no server-side verification for bits cost)

To find your channel ID, there are many 3rd party websites where you can get this channel ID with your username.

Initializing the package with your settings is as follows:
```python
cc = ChatClicks(
    channel_id="12345678",             # Channel ID of the broadcaster.
    sub_only=False,                    # Only allow subscribers to click
    allow_anonymous=False,             # Allow anonymous users to click (users that are not logged in)
    max_poll_time=10,                  # Amount of time in seconds to poll clicks
    sub_boost=1,                       # Amount of extra weight a subscriber has
    priority_boost=19,                 # Extra weight a priority user has
    priority_votes=20,                 # Amount of priority clicks a priority user gets
    tug_weight=10,                     # The weight of the tug for the chaos/order bits transaction
    dimensions="1920x1080",            # Dimensions of the screen to click on
    ban_list=[],                       # List of banned usernames
    check_coords_func=check_coords,    # Function that verifies if a click coordinates are valid
    poll_callback=poll_handler         # Function that is called after polling time
)
```
Many of these settings are for bits. If you don't have bits enabled, you do not need to worry about them. They have default settings that will have no effect on your program. the ```poll_callback``` setting will be called after polling time. It contains the center point as well as all clicks if you want to do your own calculations with that data.

This package should be used with a twitch plays chat bot, maybe even a browser source or OBS web sockets for more viewer engagement. You can do this pretty easily using asyncio. In the example, the Test class could be replaced with chat bot code. My recommendation would be to allow users to increment/decrement the ```ChatClicks.tug_of_war``` property using a chat command or something like that.

## Example

All you need is the channel ID of the broadcaster to get this to work.

You must use asyncio for your program. 

The following is a basic example:
```python
from chatclicks import ChatClicks
import asyncio
import pydirectinput as pdi

# This is where you want to check if a click coordinates are valid.
# This is just a small example that disables drag.
async def check_coords(data):
    if data["type"] == "drag":
        return False
    else:
        # check left/right click
        pass
    return True

# center contains the coordinates for the polled 
# poll_dict contains all the clicks from all the users within the polling time.
# This is where you would decide where to click.
# The minimum polling time is 1/20th of a second (0.05s), and initiates at half of the max_poll_time.
async def poll_handler(center, poll_dict):
    if center["type"] == "drag":
        pdi.moveTo(center["start"]["x"], center["start"]["y"])
        pdi.dragTo(center["end"]["x"], center["end"]["y"], duration=0.025)
    else:
        pdi.moveTo(center["x"], center["y"], duration=0.025)
        pdi.click(center["x"], center["y"], button=center["type"])


cc = ChatClicks(
    channel_id="12345678",             # Channel ID of the broadcaster.
    sub_only=False,                    # Only allow subscribers to click
    allow_anonymous=False,             # Allow anonymous users to click (users that are not logged in)
    max_poll_time=10,                  # Amount of time in seconds to poll clicks
    sub_boost=1,                       # Amount of extra weight a subscriber has
    priority_boost=19,                 # Extra weight a priority user has
    priority_votes=20,                 # Amount of priority clicks a priority user gets
    tug_weight=5,                      # The weight of the tug for the chaos/order bits transaction
    dimensions="1920x1080",            # Dimensions of the screen to click on
    ban_list=[],                       # List of banned usernames
    check_coords_func=check_coords,    # Function that verifies if a click coordinates are valid
    poll_callback=poll_handler         # Function that is called after polling time
)


# bits_cost must match the config of the chat clicks extension or user bits will be wasted.
# Leave them as None if you don't care about cheaters. 
# It is technically possible for a user to change the bit cost if they know javascript.
cc.bits_cost = {
    "priority": None,
    "chaos": None,
    "order": None
}


# You can use whatever class or function (like a chat bot for example) alongside chat clicks asynchronously like this:
class Test:
    def __init__(self) -> None:
        self.loop = asyncio.get_event_loop()

    async def test_run(self):
        c = 0
        while True:
            await asyncio.sleep(1)
            print(c := c+1)
    
    def run(self):
        return self.loop.create_task(self.test_run())

# Time to run the software.

async def main():
    await cc.ban_username("barrycarlyon")
    await cc.unban_username("barrycarlyon")
    await asyncio.gather(cc.run(), Test().run())  # Run the loops in parallel asynchronously.

# These are the event handlers. You can do whatever you want with these. If you remove them it will just default to printing data.

@cc.event(name="init")
async def on_init(data):
    print(data)

@cc.event(name="leftClick")
async def on_left_click(data):
    print("Left Click Data:", data)

@cc.event(name="rightClick")
async def on_right_click(data):
    print("Right Click Data:", data)

@cc.event(name="drag")
async def on_drag(data):
    print("Drag Data:", data)

@cc.event(name="bits")
async def on_bits(data):
    print("Bits Data:", data)
    print(cc.tug_of_war, cc.poll_time)

if __name__ == "__main__":
    asyncio.run(main())
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/WillPiledriver/chatclicks",
    "name": "chatclicks",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.5",
    "maintainer_email": "",
    "keywords": "twitch,extension,client,chat",
    "author": "WillPiledriver",
    "author_email": "willpiledriver <smifthsmurfth@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/9c/94/07f6d744a6556035f4be00c923800f6e85fc77ccf1cd6e8eff5517f4cd2c/chatclicks-0.3.5.tar.gz",
    "platform": null,
    "description": "# chatclicks\r\nPython package for the Twitch extension \"Chat Clicks\"\r\n\r\n## Installation\r\n```pip install chatclicks```\r\n\r\n## Setup\r\nThis is relatively simple to setup. Using the example below, you can really just do whatever you want with it. I will explain the main features. \r\n\r\nThe main idea is to allow chat to essentially \"vote\" on clicks. This is done by waiting an arbitrary amount of time (polling time) to collect clicks from viewers. The program then uses math that I do not understand to find the center of the most dense cluster of clicks, and then send that data over to your code. I decided not to add code that handles clicking for the simple reason that there are many different packages that do this (pyautogui, pydirectinput, etc) and they each have their own use cases so I leave that up to you. The example below uses the package pydirectinput-rgx which i recommend to use for it's compatibility with modern games.\r\n\r\nThe extension does support bits. There are three different bits products: Chaos, Order, and Priority Clicks. Chaos reduces the polling time, and order increases the polling time. Priority Clicks gives the user's clicks more weight for their next X clicks, as defined by you. Be sure to define the bits cost in your program if you don't want people to cheat (there is no server-side verification for bits cost)\r\n\r\nTo find your channel ID, there are many 3rd party websites where you can get this channel ID with your username.\r\n\r\nInitializing the package with your settings is as follows:\r\n```python\r\ncc = ChatClicks(\r\n    channel_id=\"12345678\",             # Channel ID of the broadcaster.\r\n    sub_only=False,                    # Only allow subscribers to click\r\n    allow_anonymous=False,             # Allow anonymous users to click (users that are not logged in)\r\n    max_poll_time=10,                  # Amount of time in seconds to poll clicks\r\n    sub_boost=1,                       # Amount of extra weight a subscriber has\r\n    priority_boost=19,                 # Extra weight a priority user has\r\n    priority_votes=20,                 # Amount of priority clicks a priority user gets\r\n    tug_weight=10,                     # The weight of the tug for the chaos/order bits transaction\r\n    dimensions=\"1920x1080\",            # Dimensions of the screen to click on\r\n    ban_list=[],                       # List of banned usernames\r\n    check_coords_func=check_coords,    # Function that verifies if a click coordinates are valid\r\n    poll_callback=poll_handler         # Function that is called after polling time\r\n)\r\n```\r\nMany of these settings are for bits. If you don't have bits enabled, you do not need to worry about them. They have default settings that will have no effect on your program. the ```poll_callback``` setting will be called after polling time. It contains the center point as well as all clicks if you want to do your own calculations with that data.\r\n\r\nThis package should be used with a twitch plays chat bot, maybe even a browser source or OBS web sockets for more viewer engagement. You can do this pretty easily using asyncio. In the example, the Test class could be replaced with chat bot code. My recommendation would be to allow users to increment/decrement the ```ChatClicks.tug_of_war``` property using a chat command or something like that.\r\n\r\n## Example\r\n\r\nAll you need is the channel ID of the broadcaster to get this to work.\r\n\r\nYou must use asyncio for your program. \r\n\r\nThe following is a basic example:\r\n```python\r\nfrom chatclicks import ChatClicks\r\nimport asyncio\r\nimport pydirectinput as pdi\r\n\r\n# This is where you want to check if a click coordinates are valid.\r\n# This is just a small example that disables drag.\r\nasync def check_coords(data):\r\n    if data[\"type\"] == \"drag\":\r\n        return False\r\n    else:\r\n        # check left/right click\r\n        pass\r\n    return True\r\n\r\n# center contains the coordinates for the polled \r\n# poll_dict contains all the clicks from all the users within the polling time.\r\n# This is where you would decide where to click.\r\n# The minimum polling time is 1/20th of a second (0.05s), and initiates at half of the max_poll_time.\r\nasync def poll_handler(center, poll_dict):\r\n    if center[\"type\"] == \"drag\":\r\n        pdi.moveTo(center[\"start\"][\"x\"], center[\"start\"][\"y\"])\r\n        pdi.dragTo(center[\"end\"][\"x\"], center[\"end\"][\"y\"], duration=0.025)\r\n    else:\r\n        pdi.moveTo(center[\"x\"], center[\"y\"], duration=0.025)\r\n        pdi.click(center[\"x\"], center[\"y\"], button=center[\"type\"])\r\n\r\n\r\ncc = ChatClicks(\r\n    channel_id=\"12345678\",             # Channel ID of the broadcaster.\r\n    sub_only=False,                    # Only allow subscribers to click\r\n    allow_anonymous=False,             # Allow anonymous users to click (users that are not logged in)\r\n    max_poll_time=10,                  # Amount of time in seconds to poll clicks\r\n    sub_boost=1,                       # Amount of extra weight a subscriber has\r\n    priority_boost=19,                 # Extra weight a priority user has\r\n    priority_votes=20,                 # Amount of priority clicks a priority user gets\r\n    tug_weight=5,                      # The weight of the tug for the chaos/order bits transaction\r\n    dimensions=\"1920x1080\",            # Dimensions of the screen to click on\r\n    ban_list=[],                       # List of banned usernames\r\n    check_coords_func=check_coords,    # Function that verifies if a click coordinates are valid\r\n    poll_callback=poll_handler         # Function that is called after polling time\r\n)\r\n\r\n\r\n# bits_cost must match the config of the chat clicks extension or user bits will be wasted.\r\n# Leave them as None if you don't care about cheaters. \r\n# It is technically possible for a user to change the bit cost if they know javascript.\r\ncc.bits_cost = {\r\n    \"priority\": None,\r\n    \"chaos\": None,\r\n    \"order\": None\r\n}\r\n\r\n\r\n# You can use whatever class or function (like a chat bot for example) alongside chat clicks asynchronously like this:\r\nclass Test:\r\n    def __init__(self) -> None:\r\n        self.loop = asyncio.get_event_loop()\r\n\r\n    async def test_run(self):\r\n        c = 0\r\n        while True:\r\n            await asyncio.sleep(1)\r\n            print(c := c+1)\r\n    \r\n    def run(self):\r\n        return self.loop.create_task(self.test_run())\r\n\r\n# Time to run the software.\r\n\r\nasync def main():\r\n    await cc.ban_username(\"barrycarlyon\")\r\n    await cc.unban_username(\"barrycarlyon\")\r\n    await asyncio.gather(cc.run(), Test().run())  # Run the loops in parallel asynchronously.\r\n\r\n# These are the event handlers. You can do whatever you want with these. If you remove them it will just default to printing data.\r\n\r\n@cc.event(name=\"init\")\r\nasync def on_init(data):\r\n    print(data)\r\n\r\n@cc.event(name=\"leftClick\")\r\nasync def on_left_click(data):\r\n    print(\"Left Click Data:\", data)\r\n\r\n@cc.event(name=\"rightClick\")\r\nasync def on_right_click(data):\r\n    print(\"Right Click Data:\", data)\r\n\r\n@cc.event(name=\"drag\")\r\nasync def on_drag(data):\r\n    print(\"Drag Data:\", data)\r\n\r\n@cc.event(name=\"bits\")\r\nasync def on_bits(data):\r\n    print(\"Bits Data:\", data)\r\n    print(cc.tug_of_war, cc.poll_time)\r\n\r\nif __name__ == \"__main__\":\r\n    asyncio.run(main())\r\n```\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A client for the Twitch Extension named Chat Clicks",
    "version": "0.3.5",
    "project_urls": {
        "Homepage": "https://github.com/WillPiledriver/chatclicks"
    },
    "split_keywords": [
        "twitch",
        "extension",
        "client",
        "chat"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "248746209a34f258713e19a3a133955e7daa4f8a9be0f23baf8f1af730f86888",
                "md5": "832e9acccaad552b9b0e6738342b4913",
                "sha256": "d682231878e890236803d4ef8f73794171e841c3516de1a03052f2c3aade5ec9"
            },
            "downloads": -1,
            "filename": "chatclicks-0.3.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "832e9acccaad552b9b0e6738342b4913",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.5",
            "size": 7030,
            "upload_time": "2023-10-19T22:58:24",
            "upload_time_iso_8601": "2023-10-19T22:58:24.717796Z",
            "url": "https://files.pythonhosted.org/packages/24/87/46209a34f258713e19a3a133955e7daa4f8a9be0f23baf8f1af730f86888/chatclicks-0.3.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9c9407f6d744a6556035f4be00c923800f6e85fc77ccf1cd6e8eff5517f4cd2c",
                "md5": "1c0e32a60a3ce56f0b41886978f2d2b8",
                "sha256": "bbaf4c7d940dd522e1ab99a515e6999b58d5d3f3b33df22d5a29a62f4853147c"
            },
            "downloads": -1,
            "filename": "chatclicks-0.3.5.tar.gz",
            "has_sig": false,
            "md5_digest": "1c0e32a60a3ce56f0b41886978f2d2b8",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.5",
            "size": 7475,
            "upload_time": "2023-10-19T22:58:26",
            "upload_time_iso_8601": "2023-10-19T22:58:26.632894Z",
            "url": "https://files.pythonhosted.org/packages/9c/94/07f6d744a6556035f4be00c923800f6e85fc77ccf1cd6e8eff5517f4cd2c/chatclicks-0.3.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-10-19 22:58:26",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "WillPiledriver",
    "github_project": "chatclicks",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "chatclicks"
}
        
Elapsed time: 0.14226s