From 586801d86cf0d047ca3b9fbec2be7a777cae547c Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 13 Apr 2023 10:08:55 -0500 Subject: [PATCH] random commit --- .gitignore | 179 +++++++++++++++++++++++++++++++++++++++ secrets/auth | 2 + src/config_template.yaml | 10 +++ src/main.py | 84 ++++++++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 secrets/auth create mode 100644 src/config_template.yaml create mode 100644 src/main.py diff --git a/.gitignore b/.gitignore index e69de29..e912cb8 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,179 @@ +config.yaml +config.yml + +# Created by https://www.toptal.com/developers/gitignore/api/python +# Edit at https://www.toptal.com/developers/gitignore?templates=python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +# End of https://www.toptal.com/developers/gitignore/api/python diff --git a/secrets/auth b/secrets/auth new file mode 100644 index 0000000..95d4453 --- /dev/null +++ b/secrets/auth @@ -0,0 +1,2 @@ +ID=id +SECRET=secret diff --git a/src/config_template.yaml b/src/config_template.yaml new file mode 100644 index 0000000..f2ebd3a --- /dev/null +++ b/src/config_template.yaml @@ -0,0 +1,10 @@ +user: + #watch all the user's followed channels + followed_channels: true +#additional channels to watch +channels: [] +polling: + #how many seconds to wait between checking if user channels are live + user_channels: 300 + #how many seconds to wait between checking additional channels are live + other_channels: 600 \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..d79edb9 --- /dev/null +++ b/src/main.py @@ -0,0 +1,84 @@ +from twitchAPI import Twitch +from twitchAPI.oauth import UserAuthenticator +from twitchAPI.types import AuthScope, ChatEvent +from twitchAPI.chat import Chat, EventData, ChatMessage, ChatSub, ChatCommand +import asyncio +import sys +import argparse +from ruamel.yaml import YAML + +USER_SCOPE = [AuthScope.CHAT_READ, AuthScope.CHAT_EDIT] + +class Auth: + def __init__(self, id=None, secret=None): + self.id = id + self.secret = secret + + def __eq__(self, other): + return bool(self.id == other.id and self.secret == other.secret) + + def bool(self): + return bool(self.id and self.other) + +def parse_auth(path): + with open(path) as f: + lines = f.readlines() + entries = {} + for line in lines: + if not line: + continue + if line.startswith('#'): + continue + if '=' not in line: + raise RuntimeError('invalid line in auth file') + items = line.split('=', maxsplit=1) + entries[items[0].strip().lower()] = items[1].strip() + auth = Auth( + id=entries.get('id', None), + secret=entries.get('secret', None) + ) + return auth + +def parse_config(text): + yaml = YAML() + data = yaml.load(text) + + +def main(arguments) -> int: + parser = argparse.ArgumentParser() + parser.add_argument('-A', '--auth-file', type=str, + help='path to auth file with ID=id and SECRET=secret') + parser.add_argument('--id', type=str, help='app id (overrides file if provided)') + parser.add_argument('--secret', type=str, help='app secret ' + + '(overrides file if provided)') + parser.add_argument('-c', '--channel', type=str, action='append', + help='channel to be monitored (in addition to any in config file)') + parser.add_argument('--config', type=str, help='path to config file') + args = parser.parse_args(arguments) + + config_text = '' + if args.config: + try: + with open(args.config) as f: + config_text = f.read() + except OSError: + #TODO make this stderr + print('config file not found') + return 1 + else: + try: + with open('config.yaml') as f: + config_text = f.read() + except OSError: + try: + with open('config.yml') as f: + config_text = f.read() + except OSError: + pass + if config_text: + config_data = parse_config(config_text) + + return 0 + +if __name__ == '__main__': + exit(main(sys.argv[1:])) \ No newline at end of file