mirror of
https://github.com/myned/watcher.git
synced 2024-12-24 13:07:28 +00:00
Initial upload
This commit is contained in:
parent
1d80bfeaad
commit
4b5b047203
7 changed files with 250 additions and 4 deletions
40
.gitignore
vendored
40
.gitignore
vendored
|
@ -1,3 +1,6 @@
|
||||||
|
# CUSTOM
|
||||||
|
config.toml
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
@ -20,7 +23,6 @@ parts/
|
||||||
sdist/
|
sdist/
|
||||||
var/
|
var/
|
||||||
wheels/
|
wheels/
|
||||||
pip-wheel-metadata/
|
|
||||||
share/python-wheels/
|
share/python-wheels/
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
.installed.cfg
|
.installed.cfg
|
||||||
|
@ -50,6 +52,7 @@ coverage.xml
|
||||||
*.py,cover
|
*.py,cover
|
||||||
.hypothesis/
|
.hypothesis/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
*.mo
|
*.mo
|
||||||
|
@ -72,6 +75,7 @@ instance/
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
|
||||||
# PyBuilder
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
target/
|
target/
|
||||||
|
|
||||||
# Jupyter Notebook
|
# Jupyter Notebook
|
||||||
|
@ -82,7 +86,9 @@ profile_default/
|
||||||
ipython_config.py
|
ipython_config.py
|
||||||
|
|
||||||
# pyenv
|
# pyenv
|
||||||
.python-version
|
# 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
|
# pipenv
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
@ -91,7 +97,22 @@ ipython_config.py
|
||||||
# install all needed dependencies.
|
# install all needed dependencies.
|
||||||
#Pipfile.lock
|
#Pipfile.lock
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
# 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__/
|
__pypackages__/
|
||||||
|
|
||||||
# Celery stuff
|
# Celery stuff
|
||||||
|
@ -127,3 +148,16 @@ dmypy.json
|
||||||
|
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
.pyre/
|
.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/
|
||||||
|
|
77
README.md
77
README.md
|
@ -1,2 +1,77 @@
|
||||||
# Watcher
|
# Watcher
|
||||||
Discord bot for inactive roles
|
An experimental [Hikari](https://www.hikari-py.dev) Discord bot for assigning active and inactive roles based on member activity
|
||||||
|
|
||||||
|
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/B0B1AUB66)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
A Unix-based operating system is used for the following commands\
|
||||||
|
[WSL](https://docs.microsoft.com/en-us/windows/wsl) can be used to run Linux on Windows, but is not required to run the bot
|
||||||
|
## Requirements
|
||||||
|
[Git](https://git-scm.com/downloads)\
|
||||||
|
[Python](https://www.python.org) 3.10+\
|
||||||
|
[Poetry](https://python-poetry.org/docs/master)
|
||||||
|
## Installing
|
||||||
|
Clone this repository
|
||||||
|
```
|
||||||
|
git clone https://github.com/Myned/Watcher.git
|
||||||
|
```
|
||||||
|
Go to the project folder
|
||||||
|
```
|
||||||
|
cd Watcher
|
||||||
|
```
|
||||||
|
Create a virtual environment and install dependencies
|
||||||
|
```
|
||||||
|
poetry install
|
||||||
|
```
|
||||||
|
## Usage
|
||||||
|
Go to the project folder
|
||||||
|
```
|
||||||
|
cd Watcher
|
||||||
|
```
|
||||||
|
Run with optimizations
|
||||||
|
```
|
||||||
|
poetry run python -OO run.py
|
||||||
|
```
|
||||||
|
## Setup
|
||||||
|
Run to create `config.toml`\
|
||||||
|
The file will automatically generate if it does not exist
|
||||||
|
```
|
||||||
|
client = 0 # bot application id
|
||||||
|
token = "" # bot token
|
||||||
|
activity = "you" # bot status
|
||||||
|
db = "watcher.db" # sqlite3 db filepath
|
||||||
|
guild = 0 # guild id to watch
|
||||||
|
active = 0 # active role id
|
||||||
|
inactive = 0 # inactive role id
|
||||||
|
duration = 0 # time in seconds before considered inactive
|
||||||
|
```
|
||||||
|
## Updating
|
||||||
|
Go to the project folder
|
||||||
|
```
|
||||||
|
cd Watcher
|
||||||
|
```
|
||||||
|
Pull changes from the repository
|
||||||
|
```
|
||||||
|
git pull
|
||||||
|
```
|
||||||
|
Update the virtual environment
|
||||||
|
```
|
||||||
|
poetry update
|
||||||
|
```
|
||||||
|
## Uninstalling
|
||||||
|
Remove the project folder
|
||||||
|
```
|
||||||
|
rm -rf Watcher
|
||||||
|
```
|
||||||
|
## Contributing
|
||||||
|
1. [Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) this repository on GitHub
|
||||||
|
2. Make changes to the code
|
||||||
|
3. Format the code with [Black](https://black.readthedocs.io/en/stable) inside the project folder
|
||||||
|
```
|
||||||
|
poetry run python black .
|
||||||
|
```
|
||||||
|
4. [Commit](https://github.com/git-guides/git-commit) the changes to the fork
|
||||||
|
5. Create a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) from the fork
|
||||||
|
## Credits
|
||||||
|
[hikari](https://github.com/hikari-py/hikari)\
|
||||||
|
[hikari-lightbulb](https://github.com/tandemdude/hikari-lightbulb)
|
||||||
|
|
27
config.py
Normal file
27
config.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import toml
|
||||||
|
import hikari
|
||||||
|
|
||||||
|
|
||||||
|
# Hikari activity type
|
||||||
|
# https://www.hikari-py.dev/hikari/presences.html#hikari.presences.ActivityType
|
||||||
|
ACTIVITY = hikari.ActivityType.WATCHING
|
||||||
|
# Default bot configuration
|
||||||
|
CONFIG = """\
|
||||||
|
client = 0 # bot application id
|
||||||
|
token = "" # bot token
|
||||||
|
activity = "you" # bot status
|
||||||
|
db = "watcher.db" # sqlite3 db filepath
|
||||||
|
guild = 0 # guild id to watch
|
||||||
|
active = 0 # active role id
|
||||||
|
inactive = 0 # inactive role id
|
||||||
|
duration = 0 # time in seconds before considered inactive
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Load or create config.toml
|
||||||
|
try:
|
||||||
|
config = toml.load("config.toml")
|
||||||
|
except FileNotFoundError:
|
||||||
|
with open("config.toml", "w") as f:
|
||||||
|
f.write(CONFIG)
|
||||||
|
print("config.toml created with default values. Restart when modified")
|
||||||
|
exit()
|
2
poetry.toml
Normal file
2
poetry.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[virtualenvs]
|
||||||
|
in-project = true
|
24
pyproject.toml
Normal file
24
pyproject.toml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[tool.poetry]
|
||||||
|
name = "watcher"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Watcher Discord Bot"
|
||||||
|
authors = ["Myned <dev@myned.dev>"]
|
||||||
|
license = "MIT"
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = "~3.10"
|
||||||
|
toml = "*"
|
||||||
|
uvloop = "*"
|
||||||
|
sqlitedict = "*"
|
||||||
|
hikari = {extras = ["speedups"], version = "*"}
|
||||||
|
hikari-lightbulb = "*"
|
||||||
|
|
||||||
|
[tool.poetry.dev-dependencies]
|
||||||
|
black = "*"
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core>=1.0.0"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
32
run.py
Normal file
32
run.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import os
|
||||||
|
import hikari
|
||||||
|
import lightbulb
|
||||||
|
from lightbulb.ext import tasks
|
||||||
|
|
||||||
|
import config as c
|
||||||
|
|
||||||
|
|
||||||
|
# Unix optimizations
|
||||||
|
# https://github.com/hikari-py/hikari#uvloop
|
||||||
|
if os.name != "nt":
|
||||||
|
import uvloop
|
||||||
|
|
||||||
|
uvloop.install()
|
||||||
|
|
||||||
|
|
||||||
|
bot = lightbulb.BotApp(token=c.config["token"], intents=hikari.Intents.ALL_GUILDS)
|
||||||
|
|
||||||
|
|
||||||
|
# Listener for global exceptions
|
||||||
|
@bot.listen(hikari.ExceptionEvent)
|
||||||
|
async def on_error(event):
|
||||||
|
exception = event.exception.__cause__ or event.exception
|
||||||
|
|
||||||
|
await (await bot.rest.fetch_application()).owner.send(f"```❗ {type(exception).__name__}: {exception}```")
|
||||||
|
|
||||||
|
raise event.exception
|
||||||
|
|
||||||
|
|
||||||
|
tasks.load(bot)
|
||||||
|
bot.load_extensions_from("tasks")
|
||||||
|
bot.run(activity=hikari.Activity(name=c.config["activity"], type=c.ACTIVITY) if c.config["activity"] else None)
|
52
tasks/activity.py
Normal file
52
tasks/activity.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import datetime as dt
|
||||||
|
import sqlitedict
|
||||||
|
import hikari
|
||||||
|
import lightbulb
|
||||||
|
from lightbulb.ext import tasks
|
||||||
|
|
||||||
|
import config as c
|
||||||
|
|
||||||
|
|
||||||
|
plugin = lightbulb.Plugin("activity")
|
||||||
|
db = sqlitedict.SqliteDict(c.config["db"], tablename=str(c.config["guild"]), autocommit=True)
|
||||||
|
|
||||||
|
|
||||||
|
# Check every minute if inactive
|
||||||
|
@tasks.task(s=60)
|
||||||
|
async def check_activity():
|
||||||
|
for author_id, timestamp in db.items():
|
||||||
|
if dt.datetime.now(dt.timezone.utc) - timestamp >= dt.timedelta(seconds=c.config["duration"]):
|
||||||
|
member = plugin.bot.cache.get_member(c.config["guild"], author_id)
|
||||||
|
|
||||||
|
if c.config["active"] and c.config["active"] in member.role_ids:
|
||||||
|
await member.remove_role(c.config["active"])
|
||||||
|
if c.config["inactive"] and c.config["inactive"] not in member.role_ids:
|
||||||
|
await member.add_role(c.config["inactive"])
|
||||||
|
|
||||||
|
|
||||||
|
# Listener for bot ready
|
||||||
|
@plugin.listener(hikari.StartedEvent)
|
||||||
|
async def on_ready(event):
|
||||||
|
check_activity.start()
|
||||||
|
|
||||||
|
|
||||||
|
# Listener for guild messages
|
||||||
|
@plugin.listener(hikari.GuildMessageCreateEvent)
|
||||||
|
async def on_message(event):
|
||||||
|
if event.is_bot or event.guild_id != c.config["guild"]:
|
||||||
|
return
|
||||||
|
|
||||||
|
db[event.author_id] = event.message.timestamp # or datetime.datetime.utcnow()
|
||||||
|
|
||||||
|
if c.config["active"] and c.config["active"] not in event.member.role_ids:
|
||||||
|
await event.member.add_role(c.config["active"])
|
||||||
|
if c.config["inactive"] and c.config["inactive"] in event.member.role_ids:
|
||||||
|
await event.member.remove_role(c.config["inactive"])
|
||||||
|
|
||||||
|
|
||||||
|
def load(bot):
|
||||||
|
bot.add_plugin(plugin)
|
||||||
|
|
||||||
|
|
||||||
|
def unload(bot):
|
||||||
|
bot.remove_plugin(plugin)
|
Loading…
Reference in a new issue