Skip to content
This repository was archived by the owner on Oct 27, 2022. It is now read-only.

Commit b23496f

Browse files
committed
Merge branch 'develop'
2 parents 8becee4 + 0a5bf0d commit b23496f

File tree

9 files changed

+153
-50
lines changed

9 files changed

+153
-50
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ coverage.xml
5353
*.log
5454
local_settings.py
5555
pep8.txt
56+
test.db
5657

5758
# Flask stuff:
5859
instance/
@@ -92,3 +93,4 @@ ENV/
9293
# PyDev
9394
.project
9495
.pydevproject
96+
.settings/

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
This project uses [Semantic Versioning](http://semver.org/).
44

5+
## [0.1.3] -- 2016-08-14
6+
### Fixed
7+
- Corrected all PEP8 issues.
8+
9+
### Updated
10+
- Documented all settings options.
11+
512
## [0.1.2] -- 2016-08-13
613

714
### Fixed
@@ -22,5 +29,6 @@ This project uses [Semantic Versioning](http://semver.org/).
2229
Initial release.
2330

2431

32+
[0.1.3]: https://github.com/mrogaski/django-discord-bind/compare/0.1.2...0.1.3
2533
[0.1.2]: https://github.com/mrogaski/django-discord-bind/compare/0.1.1...0.1.2
2634
[0.1.1]: https://github.com/mrogaski/django-discord-bind/compare/0.1.0...0.1.1

README.rst

+89-18
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,107 @@
22
django-discord-bind
33
===================
44

5-
This is a simple Django app that allows users to bind their Discord accounts
6-
to their Django accounts and join a partner Discord server using the OAuth2
7-
functionality of the Discord API.
5+
*A Django app for securely associating a user with a Discord account.*
86

9-
Quick start
10-
-----------
7+
.. image:: https://badge.fury.io/py/django-discord-bind.svg
8+
:target: https://badge.fury.io/py/django-discord-bind
9+
.. image:: https://travis-ci.org/mrogaski/django-discord-bind.svg?branch=master
10+
:target: https://travis-ci.org/mrogaski/django-discord-bind
1111

12-
1. Add "discord_bind" to your INSTALLED_APPS setting like this::
12+
13+
This is a simple Django application that allows users to associate one or
14+
more Discord accounts to their Django accounts and automatically join a
15+
partner Discord server using the
16+
`OAuth2 functionality of the Discord API <https://discordapp.com/developers/docs/topics/oauth2>`_.
17+
18+
Requirements
19+
------------
20+
21+
* Python 2.7, 3.4, 3.5
22+
* Django 1.9, 1.10
23+
24+
25+
Installation
26+
------------
27+
28+
Install with pip::
29+
30+
pip install django-discord-bind
31+
32+
Add `discord_bind` to your `INSTALLED_APPS` setting:
33+
34+
.. code-block:: python
1335
1436
INSTALLED_APPS = [
1537
...
1638
'discord_bind',
1739
]
1840
19-
2. Include the polls URLconf in your project urls.py like this::
41+
Include the URL configuration in your project **urls.py**:
42+
43+
.. code-block:: python
44+
45+
urlpatterns = [
46+
...
47+
url(r'^discord/', include('discord_bind.urls')),
48+
]
49+
50+
Run ``python manage.py migrate`` to create the discord_bind models.
51+
52+
53+
Configuration
54+
-------------
55+
56+
Required Settings
57+
^^^^^^^^^^^^^^^^^
58+
59+
DISCORD_CLIENT_ID
60+
The client identifier issued by the Discord authorization server. This
61+
identifier is used in the authorization request of the OAuth 2.0
62+
Authorization Code Grant workflow.
63+
64+
DISCORD_CLIENT_SECRET
65+
A shared secret issued by the Discord authorization server. This
66+
identifier is used in the access token request of the OAuth 2.0
67+
Authorization Code Grant workflow.
68+
69+
70+
Optional Settings
71+
^^^^^^^^^^^^^^^^^
72+
73+
DISCORD_AUTHZ_PATH
74+
The path of the authorization request service endpoint, which will be
75+
appended to the DISCORD_BASE_URI setting.
76+
77+
Default: /oauth2/authorize
78+
79+
DISCORD_BASE_URI
80+
The base URI for the Discord API.
81+
82+
Default: https://discordapp.com/api
83+
84+
DISCORD_INVITE_URI
85+
The URI that the user will be redirected to after one or more successful
86+
auto-invites.
87+
88+
Default: https://discordapp.com/channels/@me
89+
90+
DISCORD_RETURN_URI
91+
The URI that the user will be redirected to if no auto-invites are
92+
attempted or successful.
2093

21-
url(r'^discord/', include('discord_bind.urls')),
94+
Default: /
2295

23-
3. Run `python manage.py migrate` to create the discord_bind models.
96+
DISCORD_TOKEN_PATH
97+
The path of the access token request service endpoint, which will be
98+
appended to the DISCORD_BASE_URI setting.
2499

25-
4. Start the development server and visit http://127.0.0.1:8000/admin/
26-
to add a Discord invite code (you'll need the Admin app enabled).
100+
Default: /oauth2/token
27101

28-
5. Visit https://discordapp.com/developers/applications/me to create
29-
an application. Add http://127.0.0.1:8000/discord/cb as a redirect URI.
30102

31-
6. Add the Client ID and Secret values to the project settings.py file::
103+
License
104+
-------
32105

33-
DISCORD_CLIENT_ID = 212763200357720576
34-
DISCORD_CLIENT_SECRET = MfpBbcX2Ga3boNhoQoBTdHNUS2B1xX8f
106+
django-discord-bind is released under the terms of the MIT license.
107+
Full details in LICENSE file.
35108

36-
5. Visit http://127.0.0.1:8000/discord/ to bind your Discord account and
37-
auto-accept the invite code.

discord_bind/admin.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
from discord_bind.app_settings import BASE_URI
3232

33+
3334
@admin.register(DiscordUser)
3435
class DiscordUserAdmin(admin.ModelAdmin):
3536
list_display = ('user',
@@ -43,7 +44,9 @@ class DiscordUserAdmin(admin.ModelAdmin):
4344
'fields': ('user',),
4445
}),
4546
('Discord Account', {
46-
'fields': ('uid', ('username', 'discriminator'), 'email', 'avatar'),
47+
'fields': ('uid',
48+
('username', 'discriminator'),
49+
'email', 'avatar'),
4750
}),
4851
('OAuth2', {
4952
'classes': ('collapse',),
@@ -63,6 +66,7 @@ class DiscordUserAdmin(admin.ModelAdmin):
6366
'uid',
6467
'email']
6568

69+
6670
@admin.register(DiscordInvite)
6771
class DiscordInviteAdmin(admin.ModelAdmin):
6872
list_display = ('code',

discord_bind/models.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class DiscordUser(models.Model):
5252
def __str__(self):
5353
return self.username + '.' + self.discriminator
5454

55+
5556
@python_2_unicode_compatible
5657
class DiscordInvite(models.Model):
5758
""" Discord instant invites """
@@ -96,6 +97,8 @@ def update_context(self):
9697
except KeyError:
9798
pass
9899
else:
99-
logger.error('failed to fetch data for Discord invite %s: %d %s' % (
100-
self.code, r.status_code, r.reason))
100+
logger.error(('failed to fetch data for '
101+
'Discord invite %s: %d %s') % (self.code,
102+
r.status_code,
103+
r.reason))
101104
return result

discord_bind/tests/test_models.py

+31-19
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,39 @@ def test_discord_user(self):
5050
uid='172150183260323840',
5151
username='Henry G. Tiger',
5252
discriminator='1738')
53-
self.assertEqual(str(u), '%s.%s' %(u.username, u.discriminator))
53+
self.assertEqual(str(u), '%s.%s' % (u.username, u.discriminator))
5454

5555

5656
class TestDiscordInvite(TestCase):
5757

5858
def setUp(self):
5959
self.red = Group.objects.create(name='Red Team')
6060
self.blue = Group.objects.create(name='Blue Team')
61+
self.invite_json = {"code": "aY1XeQGDKL8iCRvJ",
62+
"guild": {
63+
"splash": None,
64+
"id": "132196927679889408",
65+
"icon": "b472e4221e5b24f4de1583be747ca1bd",
66+
"name": "Alea Iacta Est"},
67+
"channel": {"type": "text",
68+
"id": "132196927679889408",
69+
"name": "general"}}
6170

6271
def tearDown(self):
6372
self.red.delete()
6473
self.blue.delete()
6574
pass
6675

6776
def test_discord_invite(self):
68-
DiscordInvite.objects.create(code='EzqS3tytSpUCa7Lr', active=True)
77+
DiscordInvite.objects.create(code='EzqS3tytSpUCa7Lr',
78+
active=True)
6979

70-
inv = DiscordInvite.objects.create(code='8UQcx0Ychpq1Kmqs', active=True)
80+
inv = DiscordInvite.objects.create(code='8UQcx0Ychpq1Kmqs',
81+
active=True)
7182
inv.groups.add(self.blue)
7283

73-
inv = DiscordInvite.objects.create(code='9dbFpT89bmXzejG9', active=False)
84+
inv = DiscordInvite.objects.create(code='9dbFpT89bmXzejG9',
85+
active=False)
7486
inv.groups.add(self.red)
7587

7688
inv = DiscordInvite.objects.create(code='pMqXoCQT41S7e4LK')
@@ -79,30 +91,30 @@ def test_discord_invite(self):
7991

8092
with self.assertRaises(IntegrityError):
8193
with transaction.atomic():
82-
DiscordInvite.objects.create(code='EzqS3tytSpUCa7Lr', active=True)
94+
DiscordInvite.objects.create(code='EzqS3tytSpUCa7Lr',
95+
active=True)
8396

84-
self.assertEqual(DiscordInvite.objects.filter(groups=self.blue).count(), 2)
85-
self.assertEqual(DiscordInvite.objects.filter(groups=self.red).count(), 2)
86-
self.assertEqual(DiscordInvite.objects.filter(groups__isnull=True).count(), 1)
97+
self.assertEqual(DiscordInvite.objects.filter(groups=self.blue
98+
).count(), 2)
99+
self.assertEqual(DiscordInvite.objects.filter(groups=self.red
100+
).count(), 2)
101+
self.assertEqual(DiscordInvite.objects.filter(groups__isnull=True
102+
).count(), 1)
87103

88-
self.assertEqual(DiscordInvite.objects.filter(active=True).count(), 2)
89-
self.assertEqual(DiscordInvite.objects.filter(active=False).count(), 2)
104+
self.assertEqual(DiscordInvite.objects.filter(active=True
105+
).count(), 2)
106+
self.assertEqual(DiscordInvite.objects.filter(active=False
107+
).count(), 2)
90108

91109
@patch('discord_bind.models.requests.get')
92110
def test_invite_update(self, mock_get):
93111
mock_get.return_value = mock_response = Mock()
94112
mock_response.status_code = 200
95-
mock_response.json.return_value = {"code": "aY1XeQGDKL8iCRvJ",
96-
"guild": {"splash": None,
97-
"id": "132196927679889408",
98-
"icon": "b472e4221e5b24f4de1583be747ca1bd",
99-
"name": "Alea Iacta Est"},
100-
"channel": {"type": "text",
101-
"id": "132196927679889408",
102-
"name": "general"}}
113+
mock_response.json.return_value = self.invite_json
103114
obj = DiscordInvite.objects.create(code='aY1XeQGDKL8iCRvJ')
104115
obj.update_context()
105-
mock_get.assert_called_once_with('https://discordapp.com/api/invites/aY1XeQGDKL8iCRvJ')
116+
mock_get.assert_called_once_with('https://discordapp.com/api'
117+
'/invites/aY1XeQGDKL8iCRvJ')
106118
self.assertEqual(obj.guild_id, "132196927679889408")
107119
self.assertEqual(obj.guild_name, "Alea Iacta Est")
108120
self.assertEqual(obj.guild_icon, "b472e4221e5b24f4de1583be747ca1bd")

discord_bind/urls.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@
3232
urlpatterns = [
3333
url(r'^$', views.index, name='discord_bind_index'),
3434
url(r'^cb$', views.callback, name='discord_bind_callback'),
35-
]
35+
]

discord_bind/views.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def oauth_session(request, state=None, token=None):
6060
token=token,
6161
state=state)
6262

63+
6364
@login_required
6465
def index(request):
6566
# Record the final redirect alternatives
@@ -79,6 +80,7 @@ def index(request):
7980
request.session['discord_bind_oauth_state'] = state
8081
return HttpResponseRedirect(url)
8182

83+
8284
@login_required
8385
def callback(request):
8486
def decompose_data(user, token):
@@ -136,14 +138,16 @@ def bind_user(request, data):
136138
r = oauth.post(BASE_URI + '/invites/' + invite.code)
137139
if r.status_code == requests.codes.ok:
138140
count += 1
139-
logger.info('accepted Discord invite for %s/%s' % (invite.guild_name,
140-
invite.channel_name))
141+
logger.info(('accepted Discord '
142+
'invite for %s/%s') % (invite.guild_name,
143+
invite.channel_name))
141144
else:
142-
logger.error('failed to accept Discord invite for %s/%s: %d %s' %
143-
(invite.guild_name,
144-
invite.channel_name,
145-
r.status_code,
146-
r.reason))
145+
logger.error(('failed to accept Discord '
146+
'invite for %s/%s: %d %s') % (invite.guild_name,
147+
invite.channel_name,
148+
r.status_code,
149+
r.reason))
150+
147151
# Select return target
148152
if count > 0:
149153
messages.success(request, '%d Discord invite(s) accepted.' % count)
@@ -157,4 +161,3 @@ def bind_user(request, data):
157161
del request.session['discord_bind_return_uri']
158162

159163
return HttpResponseRedirect(url)
160-

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
setup(
3838
name='django-discord-bind',
39-
version='0.1.2',
39+
version='0.1.3',
4040
packages=find_packages(),
4141
include_package_data=True,
4242
license='MIT License', # example license

0 commit comments

Comments
 (0)