aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig15
-rw-r--r--.gitignore126
-rw-r--r--.token1
-rw-r--r--README.md0
-rw-r--r--discord_ban_list/__init__.py9
-rw-r--r--discord_ban_list/api.py39
-rw-r--r--discord_ban_list/result.py109
-rw-r--r--discord_ban_list/version.py31
-rw-r--r--pylintrc.cfg2
-rw-r--r--requirements.txt1
-rw-r--r--setup.cfg5
-rw-r--r--setup.py39
-rw-r--r--tests/test_login.py32
13 files changed, 409 insertions, 0 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..f8fb98d
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+charset = utf-8
+trim_trailing_whitespace = true
+max_line_length = 79
+
+[*.py]
+indent_style = space
+indent_size = 4
+spaces_around_operators = hybrid
+spaces_around_brackets = none
+quote_type = single
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f5e1e51
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,126 @@
+
+# Created by https://www.gitignore.io/api/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/
+*.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/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# 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/
+
+### Python Patch ###
+.venv/
+
+### Python.VirtualEnv Stack ###
+# Virtualenv
+# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
+[Bb]in
+[Ii]nclude
+[Ll]ib
+[Ll]ib64
+[Ll]ocal
+[Ss]cripts
+pyvenv.cfg
+pip-selfcheck.json
+
+
+# End of https://www.gitignore.io/api/python
diff --git a/.token b/.token
new file mode 100644
index 0000000..a542ed2
--- /dev/null
+++ b/.token
@@ -0,0 +1 @@
+4_zlAypGMldMW3EUcIqFFz_zTTbepiVDRTff1Gy4eI0 \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/discord_ban_list/__init__.py b/discord_ban_list/__init__.py
new file mode 100644
index 0000000..56976b2
--- /dev/null
+++ b/discord_ban_list/__init__.py
@@ -0,0 +1,9 @@
+from .api import DiscordBanList
+from .result import BanABC, NoBan, Ban
+from .version import VersionInfo, version
+
+__all__ = (
+ 'VersionInfo', 'version',
+ 'DiscordBanList',
+ 'BanABC', 'Ban', 'NoBan',
+)
diff --git a/discord_ban_list/api.py b/discord_ban_list/api.py
new file mode 100644
index 0000000..a9aec10
--- /dev/null
+++ b/discord_ban_list/api.py
@@ -0,0 +1,39 @@
+from asyncio import Lock
+from typing import Union
+
+from aiohttp import ClientSession
+
+from .result import Ban, NoBan, BanABC
+
+CHECK_URL = 'https://bans.discord.id/api/check.php'
+
+
+class DiscordBanList(object):
+ __slots__ = ('token', '_client', '_client_lock')
+
+ def __init__(self, token: str, _client: ClientSession = None):
+ self.token = token
+ self._client = _client
+ self._client_lock = Lock()
+
+ async def login(self):
+ await self._guarantee_client()
+
+ async def check(self, user_id: Union[int, str]) -> BanABC:
+ resp = await self._get('{base}?user_id={user_id}'.format(base=CHECK_URL, user_id=user_id))
+ if resp['banned'] == "0":
+ return NoBan(user_id)
+ return Ban(user_id, resp['reason'], resp['case_id'], resp['proof'])
+
+ async def _get(self, url):
+ async with self._client.get(url,
+ headers={'Authorization': self.token}) as resp:
+ resp.raise_for_status()
+ return await resp.json(content_type=None)
+
+ async def _guarantee_client(self):
+ if self._client is None:
+ async with self._client_lock:
+ if self._client is None:
+ self._client = ClientSession()
+ return self._client
diff --git a/discord_ban_list/result.py b/discord_ban_list/result.py
new file mode 100644
index 0000000..bde3e2b
--- /dev/null
+++ b/discord_ban_list/result.py
@@ -0,0 +1,109 @@
+from abc import ABC, abstractproperty, abstractmethod
+from typing import Union, Optional
+
+
+class BanABC(ABC):
+ __slots__ = ()
+
+ @abstractproperty
+ def user_id(self) -> int:
+ pass
+
+ @abstractproperty
+ def banned(self) -> bool:
+ pass
+
+ @abstractproperty
+ def reason(self) -> Optional[str]:
+ pass
+
+ @abstractproperty
+ def case_id(self) -> Optional[int]:
+ pass
+
+ @abstractproperty
+ def proof(self) -> Optional[str]:
+ pass
+
+ @abstractmethod
+ def __eq__(self, other):
+ pass
+
+
+class Ban(BanABC):
+ __slots__ = ('_proof', '_user_id', '_case_id', '_reason')
+
+ def __init__(self, user_id: Union[int, str], reason: str, case_id: Union[str, int], proof: str):
+ self._user_id = int(user_id)
+ self._reason = reason
+ self._case_id = int(case_id)
+ self._proof = proof
+
+ @property
+ def user_id(self) -> Optional[int]:
+ return self._user_id
+
+ @property
+ def banned(self) -> bool:
+ return True
+
+ @property
+ def reason(self) -> Optional[str]:
+ return self._reason
+
+ @property
+ def case_id(self) -> Optional[int]:
+ return self._case_id
+
+ @property
+ def proof(self) -> Optional[str]:
+ return self._proof
+
+ def __str__(self):
+ return '<DBan banned: True, User: {user}, Case: {case}, reason: {reason!r}, proof: {proof!r}>'.format(
+ user=self.user_id,
+ case=self.case_id,
+ reason=self.reason,
+ proof=self.proof,
+ )
+
+ def __eq__(self, other):
+ if not isinstance(other, Ban):
+ return False
+ return other.user_id == self.user_id \
+ and other.case_id == self.case_id
+
+
+class NoBan(BanABC):
+ __slots__ = ('_user_id',)
+
+ def __init__(self, user_id: Union[str, int]):
+ self._user_id = int(user_id)
+
+ @property
+ def user_id(self) -> int:
+ return self._user_id
+
+ @property
+ def banned(self) -> bool:
+ return False
+
+ @property
+ def reason(self) -> Optional[str]:
+ return None
+
+ @property
+ def case_id(self) -> Optional[int]:
+ return None
+
+ @property
+ def proof(self) -> Optional[str]:
+ return None
+
+ def __str__(self):
+ return '<DBan banned: False, User: {user}>'.format(user=self.user_id)
+
+ def __eq__(self, other):
+ if not isinstance(other, NoBan):
+ return False
+ return other.user_id == self.user_id
diff --git a/discord_ban_list/version.py b/discord_ban_list/version.py
new file mode 100644
index 0000000..3fc3d54
--- /dev/null
+++ b/discord_ban_list/version.py
@@ -0,0 +1,31 @@
+"""versioninfo for discord_ban_list"""
+
+
+# pylint: disable=too-few-public-methods
+class VersionInfo:
+ """Version info dataclass"""
+
+ __slots__ = ('major', 'minor', 'build', 'level', 'serial')
+
+ # pylint: disable=too-many-arguments
+ def __init__(self, major: int, minor: int, build: int, level: str, serial: int):
+ self.major = major
+ self.minor = minor
+ self.build = build
+ self.level = level
+ self.serial = serial
+
+ def __str__(self):
+ return '{major}.{minor}.{build}{level}{serial}'.format(
+ major=self.major,
+ minor=self.minor,
+ build=self.build,
+ level=self.level,
+ serial=self.serial,
+ )
+
+ def __repr__(self):
+ return str(self)
+
+
+version = VersionInfo(1, 0, 0, 'a', 0)
diff --git a/pylintrc.cfg b/pylintrc.cfg
new file mode 100644
index 0000000..facac26
--- /dev/null
+++ b/pylintrc.cfg
@@ -0,0 +1,2 @@
+[MASTER]
+ignore=tests, setup.py
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..ee4ba4f
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+aiohttp
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..bdd3e25
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[aliases]
+test = pytest
+
+[tool:pytest]
+addopts = --pylint --pylint-rcfile=pylintrc.cfg
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..2bece50
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,39 @@
+from setuptools import setup
+
+with open('discord_ban_list/version.py') as fp:
+ _loc, _glob = {}, {}
+ exec(fp.read(), _loc, _glob)
+ version = {**_loc, **_glob}['version']
+
+with open('requirements.txt') as fp:
+ requirements = fp.read().splitlines()
+
+with open('README.md') as fp:
+ readme = fp.read()
+
+if not version:
+ raise RuntimeError('Version is not set in discord_ban_list/version.py')
+
+setup(
+ name='discord_ban_list',
+ author='romangraef',
+ url='https://github.com/romangraef/discord_ban_list',
+ version=str(version),
+ install_requires=requirements,
+ long_description=readme,
+ setup_requires=['pytest-runner', 'pytest-pylint'],
+ tests_require=['pytest', 'pylint'],
+ license='MIT',
+ packages=['discord_ban_list'],
+ description='Asyncio Python Wrapper for the discord.id ban list.',
+ classifiers=[
+ 'Topic :: Discord',
+ 'Operating System :: OS Independent',
+ 'Topic :: Internet',
+ 'Topic :: Software Development :: Libraries',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: Utilities',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ ]
+)
diff --git a/tests/test_login.py b/tests/test_login.py
new file mode 100644
index 0000000..fb8f086
--- /dev/null
+++ b/tests/test_login.py
@@ -0,0 +1,32 @@
+import os
+from asyncio import get_event_loop
+from unittest import TestCase
+
+from discord_ban_list import DiscordBanList
+
+
+async def a_test_valid_login():
+ ban_list = DiscordBanList(os.environ['token'])
+ await ban_list.login()
+ ban = await ban_list.check(123)
+ assert not ban.banned
+
+
+async def a_test_banned():
+ user = 123456789123456789
+ ban_list = DiscordBanList(os.environ['token'])
+ await ban_list.login()
+ ban = await ban_list.check(user)
+ assert ban.banned
+ assert ban.user_id == user
+ assert ban.case_id == 9999
+ assert ban.reason == "THIS IS A VIRTUAL DBANS API TESTING ACCOUNT"
+ assert ban.proof == "https://yourmom-is.gae"
+
+
+class TestSomething(TestCase):
+ def test_not_banned(self):
+ get_event_loop().run_until_complete(a_test_valid_login())
+
+ def test_banned(self):
+ get_event_loop().run_until_complete(a_test_banned())