basic discord bot stuff
This commit is contained in:
parent
8d2b92e319
commit
e4ba87171b
6 changed files with 205 additions and 4 deletions
95
poetry.lock
generated
95
poetry.lock
generated
|
@ -1,3 +1,42 @@
|
||||||
|
[[package]]
|
||||||
|
name = "aiohttp"
|
||||||
|
version = "3.8.3"
|
||||||
|
description = "Async http client/server framework (asyncio)"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
aiosignal = ">=1.1.2"
|
||||||
|
async-timeout = ">=4.0.0a3,<5.0"
|
||||||
|
attrs = ">=17.3.0"
|
||||||
|
charset-normalizer = ">=2.0,<3.0"
|
||||||
|
frozenlist = ">=1.1.1"
|
||||||
|
multidict = ">=4.5,<7.0"
|
||||||
|
yarl = ">=1.0,<2.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
speedups = ["aiodns", "brotli", "cchardet"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aiosignal"
|
||||||
|
version = "1.2.0"
|
||||||
|
description = "aiosignal: a list of registered asynchronous callbacks"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
frozenlist = ">=1.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-timeout"
|
||||||
|
version = "4.0.2"
|
||||||
|
description = "Timeout context manager for asyncio programs"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomicwrites"
|
name = "atomicwrites"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -10,7 +49,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
name = "attrs"
|
name = "attrs"
|
||||||
version = "21.4.0"
|
version = "21.4.0"
|
||||||
description = "Classes Without Boilerplate"
|
description = "Classes Without Boilerplate"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
|
@ -58,6 +97,23 @@ python-versions = "*"
|
||||||
[package.extras]
|
[package.extras]
|
||||||
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
|
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "discord.py"
|
||||||
|
version = "2.0.1"
|
||||||
|
description = "A Python wrapper for the Discord API"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8.0"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
aiohttp = ">=3.7.4,<4"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
voice = ["PyNaCl (>=1.3.0,<1.6)"]
|
||||||
|
test = ["typing-extensions (>=4.3,<5)", "pytest-mock", "pytest-cov", "pytest-asyncio", "pytest", "coverage"]
|
||||||
|
speed = ["cchardet (==2.1.7)", "brotli", "aiodns (>=1.1)", "orjson (>=3.5.4)"]
|
||||||
|
docs = ["typing-extensions (>=4.3,<5)", "sphinxcontrib-websupport", "sphinxcontrib-trio (==1.1.2)", "sphinx (==4.4.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "faker"
|
name = "faker"
|
||||||
version = "15.1.0"
|
version = "15.1.0"
|
||||||
|
@ -69,6 +125,14 @@ python-versions = ">=3.7"
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
python-dateutil = ">=2.4"
|
python-dateutil = ">=2.4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "frozenlist"
|
||||||
|
version = "1.3.1"
|
||||||
|
description = "A list-like structure which implements collections.abc.MutableSequence"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.3"
|
version = "3.3"
|
||||||
|
@ -85,6 +149,14 @@ category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multidict"
|
||||||
|
version = "6.0.2"
|
||||||
|
description = "multidict implementation"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oauthlib"
|
name = "oauthlib"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
|
@ -316,12 +388,27 @@ brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"]
|
||||||
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
||||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yarl"
|
||||||
|
version = "1.8.1"
|
||||||
|
description = "Yet another URL library"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
idna = ">=2.0"
|
||||||
|
multidict = ">=4.0"
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "c5c99285ff355e2be2ef7a9133813b15c6b445b52f191f5720911d059b937750"
|
content-hash = "a12006faa296b74e34d600ab7300f2926d58c153fa76c15a5b73f7c91077b6ab"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
|
aiohttp = []
|
||||||
|
aiosignal = []
|
||||||
|
async-timeout = []
|
||||||
atomicwrites = [
|
atomicwrites = [
|
||||||
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
||||||
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
|
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
|
||||||
|
@ -346,7 +433,9 @@ commonmark = [
|
||||||
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
|
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
|
||||||
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
|
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
|
||||||
]
|
]
|
||||||
|
"discord.py" = []
|
||||||
faker = []
|
faker = []
|
||||||
|
frozenlist = []
|
||||||
idna = [
|
idna = [
|
||||||
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
|
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
|
||||||
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
|
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
|
||||||
|
@ -355,6 +444,7 @@ iniconfig = [
|
||||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||||
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
||||||
]
|
]
|
||||||
|
multidict = []
|
||||||
oauthlib = [
|
oauthlib = [
|
||||||
{file = "oauthlib-3.2.0-py3-none-any.whl", hash = "sha256:6db33440354787f9b7f3a6dbd4febf5d0f93758354060e802f6c06cb493022fe"},
|
{file = "oauthlib-3.2.0-py3-none-any.whl", hash = "sha256:6db33440354787f9b7f3a6dbd4febf5d0f93758354060e802f6c06cb493022fe"},
|
||||||
{file = "oauthlib-3.2.0.tar.gz", hash = "sha256:23a8208d75b902797ea29fd31fa80a15ed9dc2c6c16fe73f5d346f83f6fa27a2"},
|
{file = "oauthlib-3.2.0.tar.gz", hash = "sha256:23a8208d75b902797ea29fd31fa80a15ed9dc2c6c16fe73f5d346f83f6fa27a2"},
|
||||||
|
@ -419,3 +509,4 @@ urllib3 = [
|
||||||
{file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"},
|
{file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"},
|
||||||
{file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"},
|
{file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"},
|
||||||
]
|
]
|
||||||
|
yarl = []
|
||||||
|
|
|
@ -18,6 +18,7 @@ rich = "^12.4.4"
|
||||||
parse = "^1.19.0"
|
parse = "^1.19.0"
|
||||||
pywikibot = "^7.7.0"
|
pywikibot = "^7.7.0"
|
||||||
pyparsing = "^3.0.9"
|
pyparsing = "^3.0.9"
|
||||||
|
"discord.py" = "^2.0.1"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pytest = "^7.1.2"
|
pytest = "^7.1.2"
|
||||||
|
|
8
wiki_postbot/clients/__init__.py
Normal file
8
wiki_postbot/clients/__init__.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
"""
|
||||||
|
Bots that listen to different sources.
|
||||||
|
|
||||||
|
Quick and dirty for now, not bothering to generalize this, but in the future
|
||||||
|
would be nice to be able to have multiple clients listening to different sources,
|
||||||
|
apply (contextually modified) actions, and then optionally send on to some interface/format
|
||||||
|
"""
|
||||||
|
|
85
wiki_postbot/clients/discord_client.py
Normal file
85
wiki_postbot/clients/discord_client.py
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import discord
|
||||||
|
from discord import Client, Intents
|
||||||
|
from wiki_postbot.creds import Discord_Creds
|
||||||
|
from wiki_postbot.patterns.wikilink import Wikilink
|
||||||
|
|
||||||
|
from discord.ext import commands
|
||||||
|
from discord import Emoji
|
||||||
|
|
||||||
|
intents = Intents.default()
|
||||||
|
intents.message_content = True
|
||||||
|
|
||||||
|
bot = commands.Bot(command_prefix='/', intents=intents)
|
||||||
|
|
||||||
|
DEBUG = False
|
||||||
|
|
||||||
|
@bot.event
|
||||||
|
async def on_message(message:discord.Message):
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
if message.content == 'ping':
|
||||||
|
await message.channel.send('pong')
|
||||||
|
|
||||||
|
if 'good bot' in message.content:
|
||||||
|
await message.add_reaction("❤️🔥")
|
||||||
|
|
||||||
|
wl = Wikilink.parse(message.content)
|
||||||
|
if len(wl) > 0:
|
||||||
|
if DEBUG:
|
||||||
|
await message.channel.send(f"Wikilinks detected: \n" + '\n'.join([str(l) for l in wl]))
|
||||||
|
else:
|
||||||
|
await message.add_reaction("⏳")
|
||||||
|
|
||||||
|
await bot.process_commands(message)
|
||||||
|
|
||||||
|
@bot.command()
|
||||||
|
async def debug(ctx:discord.ext.commands.Context, arg):
|
||||||
|
print('debug command')
|
||||||
|
global DEBUG
|
||||||
|
if arg == "on":
|
||||||
|
DEBUG = True
|
||||||
|
await ctx.message.add_reaction("🧪")
|
||||||
|
elif arg == "off":
|
||||||
|
DEBUG = False
|
||||||
|
await ctx.message.add_reaction("🤐")
|
||||||
|
else:
|
||||||
|
await ctx.message.reply("usage: /debug off or /debug on")
|
||||||
|
# @bot.command
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# class MyClient(Client):
|
||||||
|
#
|
||||||
|
# def __init__(self, intents=None, **kwargs):
|
||||||
|
# if intents is None:
|
||||||
|
# intents = Intents.default()
|
||||||
|
# intents.message_content = True
|
||||||
|
#
|
||||||
|
# super(MyClient, self).__init__(intents=intents, **kwargs)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# async def on_ready(self):
|
||||||
|
# print('Logged on as', self.user)
|
||||||
|
#
|
||||||
|
# async def on_message(self, message):
|
||||||
|
# print(message)
|
||||||
|
# # don't respond to ourselves
|
||||||
|
# if message.author == self.user:
|
||||||
|
# return
|
||||||
|
#
|
||||||
|
# if message.content == 'ping':
|
||||||
|
# await message.channel.send('pong')
|
||||||
|
#
|
||||||
|
# wl = Wikilink.parse(message.content)
|
||||||
|
# if len(wl)>0:
|
||||||
|
# await message.channel.send(f"Wikilinks detected: \n" + '\n'.join([str(l) for l in wl]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
creds = Discord_Creds.from_json('discord_creds.json')
|
||||||
|
# client = MyClient()
|
||||||
|
# client.run(creds.token)
|
||||||
|
|
||||||
|
|
||||||
|
bot.run(creds.token)
|
|
@ -32,3 +32,12 @@ class Zenodo_Creds:
|
||||||
creds = json.load(jfile)
|
creds = json.load(jfile)
|
||||||
return Zenodo_Creds(**creds)
|
return Zenodo_Creds(**creds)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Discord_Creds:
|
||||||
|
token:str
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_json(cls, path:Path) -> 'Discord_Creds':
|
||||||
|
with open(path, 'r') as jfile:
|
||||||
|
creds = json.load(jfile)
|
||||||
|
return Discord_Creds(**creds)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import re
|
import re
|
||||||
from wiki_postbot.patterns import Pattern
|
from wiki_postbot.patterns.patterns import Pattern
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional, Union, List
|
from typing import Optional, Union, List
|
||||||
import pyparsing as pp
|
import pyparsing as pp
|
||||||
|
from pprint import pformat
|
||||||
|
|
||||||
|
|
||||||
WIKILINK = re.compile(r'\[\[(.*?)\]\]', re.IGNORECASE)
|
WIKILINK = re.compile(r'\[\[(.*?)\]\]', re.IGNORECASE)
|
||||||
|
@ -73,6 +74,9 @@ class NBack:
|
||||||
def __eq__(self, other:'NBack'):
|
def __eq__(self, other:'NBack'):
|
||||||
return all([getattr(self, f) == getattr(other, f) for f in self.FIELDS])
|
return all([getattr(self, f) == getattr(other, f) for f in self.FIELDS])
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return pformat({f:getattr(self, f) for f in self.FIELDS})
|
||||||
|
|
||||||
class Wikilink(Pattern):
|
class Wikilink(Pattern):
|
||||||
"""
|
"""
|
||||||
Pattern for detecting wikilinks!
|
Pattern for detecting wikilinks!
|
||||||
|
@ -84,7 +88,7 @@ class Wikilink(Pattern):
|
||||||
|
|
||||||
In each of the following examples, `LINK` is a placeholder for the text of the wikilink to be made.
|
In each of the following examples, `LINK` is a placeholder for the text of the wikilink to be made.
|
||||||
|
|
||||||
# N-Back Links
|
# N-Back Links (see :class:`.NBack`)
|
||||||
|
|
||||||
For all of these, whitespace in-between the n-back specifier and the link text will be ignored. So
|
For all of these, whitespace in-between the n-back specifier and the link text will be ignored. So
|
||||||
`[[^LINK]]` and `[[^ LINK]]` are both valid.
|
`[[^LINK]]` and `[[^ LINK]]` are both valid.
|
||||||
|
@ -171,5 +175,8 @@ class Wikilink(Pattern):
|
||||||
def __eq__(self, other:'Wikilink'):
|
def __eq__(self, other:'Wikilink'):
|
||||||
return all(getattr(self, f) == getattr(other, f) for f in self.FIELDS)
|
return all(getattr(self, f) == getattr(other, f) for f in self.FIELDS)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return pformat({f:getattr(self, f) for f in self.FIELDS if getattr(self, f) is not None})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue