Merge branch 'master' into dev

This commit is contained in:
thec0sm0s
2020-09-11 10:30:51 +05:30
7 changed files with 201 additions and 11 deletions

View File

@@ -13,12 +13,15 @@ python3 -m pip install Flask-Discord
### Basic Example
```python
import os
from flask import Flask, redirect, url_for
from flask_discord import DiscordOAuth2Session, requires_authorization, Unauthorized
app = Flask(__name__)
app.secret_key = b"random bytes representing flask secret key"
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true" # !! Only in development environment.
app.config["DISCORD_CLIENT_ID"] = 490732332240863233 # Discord client ID.
app.config["DISCORD_CLIENT_SECRET"] = "" # Discord client secret.

View File

@@ -54,6 +54,8 @@ in exchange for fetching user's details and display them on web page.
app = Flask(__name__)
app.secret_key = b"random bytes representing flask secret key"
# OAuth2 must make use of HTTPS in production environment.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true" # !! Only in development environment.
app.config["DISCORD_CLIENT_ID"] = 490732332240863233 # Discord client ID.
app.config["DISCORD_CLIENT_SECRET"] = "" # Discord client secret.
@@ -97,3 +99,26 @@ in exchange for fetching user's details and display them on web page.
if __name__ == "__main__":
app.run()
**Lazy initialization with flask factory pattern**
.. code-block:: python3
from flask_discord import DiscordOAuth2Session
discord = DiscordOAuth2Session()
def get_app():
app = Flask(__name__)
app.secret_key = b"random bytes representing flask secret key"
# OAuth2 must make use of HTTPS in production environment.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true" # !! Only in development environment.
app.config["DISCORD_CLIENT_ID"] = 490732332240863233 # Discord client ID.
app.config["DISCORD_CLIENT_SECRET"] = "" # Discord client secret.
app.config["DISCORD_REDIRECT_URI"] = "" # URL to your callback endpoint.
app.config["DISCORD_BOT_TOKEN"] = "" # Required to access BOT resources.
discord.init_app(app)
return app

View File

@@ -14,4 +14,4 @@ __all__ = [
]
__version__ = "0.1.60"
__version__ = "0.1.61"

View File

@@ -2,7 +2,6 @@ import cachetools
import requests
import typing
import json
import os
import abc
from flask_discord import configs
@@ -26,18 +25,39 @@ class DiscordOAuth2HttpClient(abc.ABC):
"DISCORD_OAUTH2_TOKEN",
]
def __init__(self, app, client_id=None, client_secret=None, redirect_uri=None, bot_token=None, users_cache=None):
self.client_id = client_id or app.config["DISCORD_CLIENT_ID"]
self.__client_secret = client_secret or app.config["DISCORD_CLIENT_SECRET"]
self.redirect_uri = redirect_uri or app.config["DISCORD_REDIRECT_URI"]
self.__bot_token = bot_token or app.config.get("DISCORD_BOT_TOKEN", str())
def __init__(
self, app=None,
client_id=None, client_secret=None, redirect_uri=None,
bot_token=None, users_cache=None
):
self.client_id = client_id
self.__client_secret = client_secret
self.redirect_uri = redirect_uri
self.__bot_token = bot_token
self.users_cache = users_cache
if app is not None:
self.init_app(app)
def init_app(self, app):
"""A method to lazily initialize the application.
Use this when you're using flask factory pattern to create your instances of your flask application.
Parameters
----------
app : Flask
An instance of your `flask application <http://flask.pocoo.org/docs/1.0/api/#flask.Flask>`_.
"""
self.client_id = self.client_id or app.config["DISCORD_CLIENT_ID"]
self.__client_secret = self.__client_secret or app.config["DISCORD_CLIENT_SECRET"]
self.redirect_uri = self.redirect_uri or app.config["DISCORD_REDIRECT_URI"]
self.__bot_token = self.__bot_token or app.config.get("DISCORD_BOT_TOKEN", str())
self.users_cache = cachetools.LFUCache(
app.config.get("DISCORD_USERS_CACHE_MAX_LIMIT", configs.DISCORD_USERS_CACHE_DEFAULT_MAX_LIMIT)
) if users_cache is None else users_cache
) if self.users_cache is None else self.users_cache
if not issubclass(self.users_cache.__class__, Mapping):
raise ValueError("Instance users_cache must be a mapping like object.")
if "http://" in self.redirect_uri:
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true"
app.discord = self
@property
@@ -141,7 +161,7 @@ class DiscordOAuth2HttpClient(abc.ABC):
).request(method, route, data, **kwargs) if oauth else requests.request(method, route, data=data, **kwargs)
if response.status_code == 401:
raise exceptions.Unauthorized
raise exceptions.Unauthorized()
if response.status_code == 429:
raise exceptions.RateLimited(response)

23
tests/__init__.py Normal file
View File

@@ -0,0 +1,23 @@
import os
from flask import Flask
from flask_discord import DiscordOAuth2Session
discord = DiscordOAuth2Session(client_id=490732332240863233)
def get_app():
app = Flask(__name__)
app.secret_key = b"%\xe0'\x01\xdeH\x8e\x85m|\xb3\xffCN\xc9g"
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true" # !! Only in development environment.
# app.config["DISCORD_CLIENT_ID"] = 490732332240863233
app.config["DISCORD_CLIENT_SECRET"] = os.getenv("DISCORD_CLIENT_SECRET")
app.config["DISCORD_BOT_TOKEN"] = os.getenv("DISCORD_BOT_TOKEN")
app.config["DISCORD_REDIRECT_URI"] = "http://127.0.0.1:5000/callback"
discord.init_app(app)
return app

View File

@@ -7,6 +7,7 @@ from flask_discord import DiscordOAuth2Session, requires_authorization
app = Flask(__name__)
app.secret_key = b"%\xe0'\x01\xdeH\x8e\x85m|\xb3\xffCN\xc9g"
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true" # !! Only in development environment.
app.config["DISCORD_CLIENT_ID"] = 490732332240863233
app.config["DISCORD_CLIENT_SECRET"] = os.getenv("DISCORD_CLIENT_SECRET")

118
tests/test_factory_app.py Normal file
View File

@@ -0,0 +1,118 @@
import os
from tests import get_app, discord
from flask import redirect, url_for
from flask_discord import requires_authorization
app = get_app()
HYPERLINK = '<a href="{}">{}</a>'
@app.route("/")
def index():
if not discord.authorized:
return f"""
{HYPERLINK.format(url_for(".login"), "Login")} <br />
{HYPERLINK.format(url_for(".login_with_data"), "Login with custom data")} <br />
{HYPERLINK.format(url_for(".invite_bot"), "Invite Bot with permissions 8")} <br />
{HYPERLINK.format(url_for(".invite_oauth"), "Authorize with oauth and bot invite")}
"""
return f"""
{HYPERLINK.format(url_for(".me"), "@ME")}<br />
{HYPERLINK.format(url_for(".logout"), "Logout")}<br />
{HYPERLINK.format(url_for(".user_guilds"), "My Servers")}<br />
{HYPERLINK.format(url_for(".add_to_guild", guild_id=475549041741135881), "Add me to 475549041741135881.")}
"""
@app.route("/login/")
def login():
return discord.create_session()
@app.route("/login-data/")
def login_with_data():
return discord.create_session(data=dict(redirect="/me/", coupon="15off", number=15, zero=0, status=False))
@app.route("/invite-bot/")
def invite_bot():
return discord.create_session(scope=["bot"], permissions=8, guild_id=464488012328468480, disable_guild_select=True)
@app.route("/invite-oauth/")
def invite_oauth():
return discord.create_session(scope=["bot", "identify"], permissions=8)
@app.route("/callback/")
def callback():
data = discord.callback()
redirect_to = data.get("redirect", "/")
return redirect(redirect_to)
@app.route("/me/")
def me():
user = discord.fetch_user()
return f"""
<html>
<head>
<title>{user.name}</title>
</head>
<body><img src='{user.avatar_url or user.default_avatar_url}' />
<p>Is avatar animated: {str(user.is_avatar_animated)}</p>
<a href={url_for("my_connections")}>Connections</a>
<br />
</body>
</html>
"""
@app.route("/me/guilds/")
def user_guilds():
guilds = discord.fetch_guilds()
return "<br />".join([f"[ADMIN] {g.name}" if g.permissions.administrator else g.name for g in guilds])
@app.route("/add_to/<int:guild_id>/")
def add_to_guild(guild_id):
user = discord.fetch_user()
return user.add_to_guild(guild_id)
@app.route("/me/connections/")
def my_connections():
user = discord.fetch_user()
connections = discord.fetch_connections()
return f"""
<html>
<head>
<title>{user.name}</title>
</head>
<body>
{str([f"{connection.name} - {connection.type}" for connection in connections])}
</body>
</html>
"""
@app.route("/logout/")
def logout():
discord.revoke()
return redirect(url_for(".index"))
@app.route("/secret/")
@requires_authorization
def secret():
return os.urandom(16)
if __name__ == "__main__":
app.run(debug=True)