mirror of
https://github.com/myned/watcher.git
synced 2024-11-01 12:22:38 +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
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
@ -20,7 +23,6 @@ parts/
|
|||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
|
@ -50,6 +52,7 @@ coverage.xml
|
|||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
@ -72,6 +75,7 @@ instance/
|
|||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
|
@ -82,7 +86,9 @@ profile_default/
|
|||
ipython_config.py
|
||||
|
||||
# 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
|
||||
# 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.
|
||||
#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__/
|
||||
|
||||
# Celery stuff
|
||||
|
@ -127,3 +148,16 @@ 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/
|
||||
|
|
77
README.md
77
README.md
|
@ -1,2 +1,77 @@
|
|||
# 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