Skip to content
Open
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
7f4740d
Merge with parent
dwitterer Oct 25, 2018
cc62f5a
Update hashtag regex
dwitterer Oct 25, 2018
a80595a
Summon the anchor annihilator
dwitterer Oct 26, 2018
8b25900
Remove a newline
dwitterer Oct 26, 2018
41612c4
Update README.md
dwitterer Oct 26, 2018
9e5226e
Fix unbalanced parenthesis
dwitterer Oct 26, 2018
f99d1db
Insert code blocks last, so the anchor annihilator can do its job
dwitterer Oct 26, 2018
ce1be01
Merge with parent
dwitterer Oct 26, 2018
a2ca8fa
Move long comments onto new lines
dwitterer Oct 26, 2018
c2a9df1
Fix other lint-python errors
dwitterer Oct 26, 2018
c6936b2
Fix other lint-python errors
dwitterer Oct 26, 2018
c3cf099
Final lint-python fixes
dwitterer Oct 26, 2018
6bbebe5
Final lint-python fixes
dwitterer Oct 26, 2018
a9a0864
Remove 2-character minimum for hashtags
dwitterer Oct 26, 2018
2eea517
Allow hashtags beginning with numbers
dwitterer Oct 26, 2018
3284320
Merge with parent
dwitterer Nov 9, 2018
cc5be1b
Automatically shorten magic links in dwitter.net/*/* form into proper…
dwitterer Nov 17, 2018
8b8a251
Spring cleaned this file up a bit
dwitterer Nov 17, 2018
6aa0770
Spring clean here also
dwitterer Nov 17, 2018
a689fd3
Clean up test_dweet
dwitterer Nov 17, 2018
a171111
Clean up test_comment
dwitterer Nov 17, 2018
5bdc35b
Update test_user_feeds.py
dwitterer Nov 17, 2018
dedaa2c
Cleaned this up
dwitterer Nov 17, 2018
db8b495
Update test_feed_views.py
dwitterer Nov 17, 2018
bf769d1
Update test_hashtag_feed_views.py
dwitterer Nov 17, 2018
95e50ab
Update test_hashtags.py
dwitterer Nov 17, 2018
e6b5431
Update test_insert_code_blocks.py
dwitterer Nov 17, 2018
0514840
Update test_insert_magic_links.py
dwitterer Nov 17, 2018
5fb05c1
Reorder insert_magic_links to autocrop urls first
dwitterer Nov 18, 2018
20cd232
Add tests for autocropping urls
dwitterer Nov 18, 2018
b91e82a
Add tests for new hashtag system and modify old ones
dwitterer Nov 18, 2018
e132d72
Modify old tests to suit new hashtag system
dwitterer Nov 18, 2018
0e7ae10
Add test case for URL autocropping with other text
dwitterer Nov 18, 2018
c64d727
Autocropping function error prevention
dwitterer Nov 20, 2018
1b9cc29
I'm an idiot
dwitterer Nov 20, 2018
4882913
I python-ed a little too hard
dwitterer Nov 20, 2018
3ff794d
Add new test cases for the anchor annihilator
dwitterer Nov 20, 2018
12af3af
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
549d100
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
0a0fb90
Update test_dweet_comments.py
dwitterer Nov 20, 2018
b3bbfa5
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
59ddbcb
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
dc4a853
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
6eea5e3
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
75ff72d
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
46c4999
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
baf715f
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
b83056f
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
a640949
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
988005d
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
400f1b4
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
e7c324a
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
99f5487
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
557ffb9
Insert missed comma
dwitterer Nov 20, 2018
af904db
Fixed lint-python errors in this file
dwitterer Nov 20, 2018
73185b5
Remove unnecessary string concatenation
dwitterer Nov 20, 2018
caf605e
Use new hashtag regex in models.py
dwitterer Nov 26, 2018
404a4c1
Make autocrop tests default to https
dwitterer Nov 26, 2018
bd67277
Made tests not fail
dwitterer Nov 26, 2018
0d856ed
Fix ordering of link insertion functions in serializers.py
dwitterer Nov 26, 2018
48f6c8c
Less confusing function names
dwitterer Nov 26, 2018
4d71b9e
Don't match invalid usernames
dwitterer Nov 26, 2018
b7d7341
New tests for username punctuation suffixing
dwitterer Nov 26, 2018
100e60a
Fix broken regexes
dwitterer Nov 26, 2018
03b17e4
Add new tests for hashtag punctuation
dwitterer Nov 26, 2018
4b76ae7
Dweet mentions can use the same punctuation rule
dwitterer Nov 26, 2018
22c8279
Add tests for dweet mention punctuation suffixing
dwitterer Nov 26, 2018
1e958c1
Typo
dwitterer Nov 26, 2018
716e0b3
Fix lint_python errors in this file
dwitterer Nov 26, 2018
23c2f3f
Fix lint-python errors in this file
dwitterer Nov 26, 2018
d4d08be
Typo
dwitterer Nov 26, 2018
9ee2aed
Fix some failing tests
dwitterer Nov 26, 2018
7e468b4
Typo
dwitterer Nov 27, 2018
910ef08
Stianjensen was right....
dwitterer Nov 27, 2018
ea6a6a7
More consistent comment formatting
dwitterer Nov 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ Join the chat on [Discord](https://discord.gg/r5nXDsQ)
Inspired by [arkt.is/t/](http://arkt.is/t/Yy53aWR0aD0yZTM7eC5maWxsUmVjdCgxNTAsMTUwKlModCkrMTUwLDE1MCwxNTAp)


## Pre-requisites and first-time installation
## Pre-requisites and first-time installation (Linux)
* Install `npm`
* `sudo apt install npm`
* Get packages needed for server and clone the repository
* Install Python and necessary Python development packages
* `sudo apt install python python-dev`
* Get packages needed for server and clone the repository
* `sudo apt install git virtualenv python-pip`
* `git clone https://github.com/lionleaf/dwitter.git`

Expand Down
4 changes: 2 additions & 2 deletions dwitter/templates/snippets/dweet_card.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
<ul class=sticky-comments>
<li class="comment sticky-comment">
<a class="comment-name sticky-comment" href="{% url 'user_feed' url_username=dweet.top_comment.author.username %}">{{ dweet.top_comment.author.username }}:</a>
<span class="comment-message sticky-comment">{{ dweet.top_comment.text | force_escape | insert_code_blocks | urlizetrunc:45 | insert_magic_links }}</span>
<span class="comment-message sticky-comment">{{ dweet.top_comment.text | force_escape | insert_magic_links | urlizetrunc:45 | insert_code_blocks }}</span>
</li>
</ul>
{% endif %}
Expand All @@ -144,7 +144,7 @@
{% if comment != dweet.top_comment or not dweet.has_sticky_comment %}
<li class=comment>
<a class=comment-name href="{% url 'user_feed' url_username=comment.author.username %}">{{ comment.author.username }}:</a>
<span class="comment-message">{{ comment.text | force_escape | insert_code_blocks | urlizetrunc:45 | insert_magic_links }}</span>
<span class="comment-message">{{ comment.text | force_escape | insert_magic_links | urlizetrunc:45 | insert_code_blocks }}</span>
</li>
{% endif %}
{% endfor %}
Expand Down
5 changes: 5 additions & 0 deletions dwitter/templatetags/insert_code_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ def to_code_block(m):
code = m.group('code')
code = re.sub(r'\\`', '`', code)

# remove anchors from code blocks
Comment thread
lionleaf marked this conversation as resolved.
a = re.findall(r'(<a[^<]*>(?P<link>[^<]*)</a>)', code)
for i in range(len(a)):
code = code.replace(a[i][0], a[i][1])

return '<code>%s</code>' % code


Expand Down
39 changes: 30 additions & 9 deletions dwitter/templatetags/insert_magic_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@
register = template.Library()


# find all long d/ and u/ links in http:// form through regex, and
# use replace() to singularly shorten each match into the d/ or u/ form
def autocrop_urls(m):
Comment thread
lionleaf marked this conversation as resolved.
d_links = re.findall(r'(?<!\S)((http(s|):\/\/|)(www\.|)dwitter\.net\/(d\/\d+))\b', m)
u_links = re.findall(r'(?<!\S)((http(s|):\/\/|)(www\.|)dwitter\.net\/(u\/\S+))\b', m)
for i in range(len(d_links)):
if d_links:
m = m.replace(d_links[i][0], d_links[i][4])
for i in range(len(u_links)):
if u_links:
m = m.replace(u_links[i][0], u_links[i][4])
return m


def user_dweet_to_link(m):
text = m.group('text')
dweet_id = m.group('dweet_id')
Expand All @@ -25,26 +39,33 @@ def hashtag_to_link(m):
url = 'h/' + hashtag
tag = '#' + hashtag

if not re.search('[a-zA-Z]', hashtag):
return tag # hashtag contains no letters, return the plain tag

result = '<a href="/{0}">{1}</a>'.format(url, tag)
return text.replace(tag, result)


@register.filter(is_safe=True)
def insert_magic_links(text):
text = autocrop_urls(text)
text = re.sub(
r'(?:^|(?<=\s))' # start of string or whitespace
r'/?' # optional /
r'(?P<text>' # capture original pattern
r'[^a-zA-Z\d]?d/(?P<dweet_id>\d+)[^a-zA-Z]?' # dweet reference
r'|' # or
r'[^a-zA-Z\d]?u/(?P<username>[\w.@+-]+)[^a-zA-Z\d]?)' # user reference
r'(?=$|\s|#)', # end of string, whitespace or hashtag
r'(?:^|(?<=\s))' # start of string or whitespace
r'/?' # optional /
r'(?P<text>' # capture original pattern
r'[^a-zA-Z\d]?d/(?P<dweet_id>\d+)[^a-zA-Z]?' # dweet reference
r'|' # or
r'[^a-zA-Z\d]?u/(?P<username>[\w.@+-]+)[^a-zA-Z\d]?)' # user reference
# end of string, whitespace or hashtag:
r'(?=$|\s|#)',
user_dweet_to_link,
text
)
text = re.sub(
r'(?P<text>' # capture original pattern
r'#(?P<hashtag>[_a-zA-Z][_a-zA-Z\d]*)[^_a-zA-Z\d]?)', # hashtag
# capture original pattern
r'(?P<text>'
# hashtag - check for whitespace precedence and word boundaries
r'(?<!\S)#(?P<hashtag>[_a-zA-Z\d]+)\b)',
hashtag_to_link,
text
)
Expand Down
1 change: 1 addition & 0 deletions dwitter/tests/dweet/test_dweet_comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def code_wrap(s):


class DweetTestCase(TransactionTestCase):

def setUp(self):
self.client = Client()
self.user = User.objects.create(username="user", password="")
Expand Down
9 changes: 7 additions & 2 deletions dwitter/tests/feed/test_feed_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from datetime import timedelta


class DweetFeedTestCase(): # Not inheriting from TestCase, an abstract test class if you will
class DweetFeedTestCase(): # not inheriting from TestCase, an abstract test class if you will

request_factory = RequestFactory()

def setUp(self):
Expand Down Expand Up @@ -49,7 +50,7 @@ def setUp(self):
for i in range(random.randrange(0, 5)):
filler_dweet.likes.add(users[i])

# Add comments with some #hashtags
# add comments with some #hashtags
Comment.objects.create(id=1,
text="comment1 text with #hashtag #test ",
posted=now - timedelta(minutes=1),
Expand Down Expand Up @@ -89,6 +90,7 @@ def test_html_response(self):


class HotDweetFeedTests(DweetFeedTestCase, TestCase):

dweetFeed = HotDweetFeed()

def test_hot_sort(self):
Expand All @@ -102,6 +104,7 @@ def test_hot_sort(self):


class TopDweetFeedTests(DweetFeedTestCase, TestCase):

dweetFeed = TopDweetFeed()

def test_top_sort(self):
Expand All @@ -115,6 +118,7 @@ def test_top_sort(self):


class NewDweetFeedTests(DweetFeedTestCase, TestCase):

dweetFeed = NewDweetFeed()

def test_new_sort(self):
Expand All @@ -127,4 +131,5 @@ def test_new_sort(self):


class RandomDweetFeedTests(DweetFeedTestCase, TestCase):

dweetFeed = RandomDweetFeed()
3 changes: 3 additions & 0 deletions dwitter/tests/feed/test_hashtag_feed_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@


class HashtagFeedTestCase(): # Not inheriting from TestCase, an abstract test class if you will

request_factory = RequestFactory()
dweetFeed = {}

Expand Down Expand Up @@ -96,6 +97,7 @@ def test_html_response(self):


class TopHashtagFeedTests(HashtagFeedTestCase, TestCase):

dweetFeed = TopHashtagFeed()

def test_top_sort(self):
Expand All @@ -109,6 +111,7 @@ def test_top_sort(self):


class NewHashtagFeedTests(HashtagFeedTestCase, TestCase):

dweetFeed = NewHashtagFeed()

def test_new_sort(self):
Expand Down
29 changes: 15 additions & 14 deletions dwitter/tests/feed/test_post_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


class PostDweetTestCase(TransactionTestCase):

def setUp(self):
self.client = Client()

Expand Down Expand Up @@ -77,18 +78,18 @@ def test_post_new_dweet_with_first_comment_with_hashtag(self):
def test_too_long_dweet_post(self):
user = self.login()

response = self.client.post('/dweet', {'code': 'test code that is way too long,' +
response = self.client.post('/dweet', {'code': 'Test code that is way too long,' +
'wow this looks long in code.' +
'We could fit so much in here.' +
'oh wow. mooooooooooooooooar text.' +
'Getting there.' +
'And BAM tooo long!'}, follow=True)
'Oh wow. Mooooooooooooooooar text.' +
'Getting there...' +
'And BAM! Tooo long!'}, follow=True)
self.assertContains(response, "Dweet code too long!", status_code=400)

# shorter code should go through!
response = self.client.post('/dweet', {'code': 'test code that is a lot shorter,' +
'wow this looks long in code.' +
'And BAM not tooo long!'}, follow=True)
response = self.client.post('/dweet', {'code': 'Test code that is a lot shorter,' +
'wow, so short...' +
'And BAM! Not too long!'}, follow=True)
self.assertEqual(response.status_code, 200)

dweets = Dweet.objects.filter(author=user)
Expand Down Expand Up @@ -149,18 +150,18 @@ def test_post_dweet_reply_with_first_comment_with_hashtag(self):
def test_too_long_dweet_reply(self):
user = self.login()

response = self.client.post('/d/1000/reply', {'code': 'test code that is way too long,' +
response = self.client.post('/d/1000/reply', {'code': 'Test code that is way too long,' +
'wow this looks long in code.' +
'We could fit so much in here.' +
'oh wow. mooooooooooooooooar text.' +
'Getting there.' +
'And BAM tooo long!'}, follow=True)
'Oh wow. Mooooooooooooooooar text.' +
'Getting there...' +
'And BAM! Tooo long!'}, follow=True)
self.assertContains(response, "Dweet code too long!", status_code=400)

# shorter code should go through!
response = self.client.post('/d/1000/reply', {'code': 'test code that is a lot shorter,' +
'wow this looks long in code.' +
'And BAM not tooo long!'}, follow=True)
response = self.client.post('/d/1000/reply', {'code': 'Test code that is a lot shorter,' +
'wow, so short...' +
'And BAM! Not tooo long!'}, follow=True)
self.assertEqual(response.status_code, 200)

dweets = Dweet.objects.filter(author=user)
Expand Down
7 changes: 6 additions & 1 deletion dwitter/tests/feed/test_user_feeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@


class UserFeedTestCase(): # Not inheriting from TestCase, an abstract test class if you will

request_factory = RequestFactory()

def setUp(self):
Expand Down Expand Up @@ -41,7 +42,7 @@ def test_all_dweet_author(self):
def test_queryset_size(self):
self.dweetFeed.kwargs = {'url_username': self.users[1].username}
queryset = self.dweetFeed.get_queryset()
# Each user have 10 dweets from setUp
# Each user has 10 dweets from setUp()
self.assertEqual(queryset.count(), 10)

def test_annotation(self):
Expand All @@ -56,18 +57,22 @@ def test_annotation(self):


class NewUserFeedTests(UserFeedTestCase, TestCase):

dweetFeed = NewUserFeed()


class TopUserFeedTests(UserFeedTestCase, TestCase):

dweetFeed = TopUserFeed()


class HotUserFeedTests(UserFeedTestCase, TestCase):

dweetFeed = HotUserFeed()


class NewLikedFeedTests(UserFeedTestCase, TestCase):

dweetFeed = NewLikedFeed()

def test_queryset_objects(self):
Expand Down
1 change: 1 addition & 0 deletions dwitter/tests/models/test_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@


class DweetTestCase(TestCase):

def setUp(self):
user1 = User.objects.create(username="user1", password="")
user2 = User.objects.create(username="user2", password="")
Expand Down
1 change: 1 addition & 0 deletions dwitter/tests/models/test_dweet.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


class DweetTestCase(TestCase):

def setUp(self):
user1 = User.objects.create(username="user1", password="")
user2 = User.objects.create(username="user2", password="")
Expand Down
19 changes: 8 additions & 11 deletions dwitter/tests/models/test_hashtags.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


class HashtagTestCase(TestCase):

def setUp(self):
user1 = User.objects.create(username="user1", password="")
self.user2 = User.objects.create(username="user2", password="")
Expand Down Expand Up @@ -41,17 +42,13 @@ def test_hashtags_created(self):
h1 = Hashtag.objects.get(name='hash1')
h2 = Hashtag.objects.get(name='hash2')

try:
illegal1 = Hashtag.objects.get(name='1hash')
self.assertEqual(illegal1, True) # should throw an exception!
except:
pass

try:
illegal2 = Hashtag.objects.get(name='2hash')
self.assertEqual(illegal2, True) # should throw an exception!
except:
pass
# These shouldn't throw any exceptions anymore,
# since hashtags staring with numbers are now allowed
one_hash = Hashtag.objects.get(name='1hash')
self.assertEqual(one_hash, True)

two_hash = Hashtag.objects.get(name='2hash')
self.assertEqual(two_hash, True)

self.assertEqual(h is None, False)
self.assertEqual(h1 is None, False)
Expand Down
21 changes: 18 additions & 3 deletions dwitter/tests/templatetags/test_insert_code_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,35 @@


class DweetTestCase(TestCase):
def test_insert_code_blocks_wraps_stuff_inside_backticks(self):

def test_insert_code_wraps_stuff_inside_backticks(self):
self.assertEqual(
'<code>a</code>',
insert_code_blocks('`a`')
)

def test_insert_code_blocks_ignores_backticks(self):
def test_insert_code_ignores_backticks(self):
self.assertEqual(
'<code>a=`b`</code>',
insert_code_blocks('`a=\`b\``')
)

def test_insert_code_blocks_is_not_greedy_with_multiple_blocks(self):
def test_insert_code_is_not_greedy_with_multiple_blocks(self):
self.assertEqual(
'a <code>1</code> b <code>2</code> c',
insert_code_blocks('a `1` b `2` c')
)

def test_insert_code_removes_anchors(self):
self.assertEqual(
'My sneaky link here, and also here',
insert_code_blocks('My sneaky <a href="1">link</a> here, and also <a href="2">here</a>')
)

def test_insert_code_with_no_code(self):
try:
insert_code_blocks('')
insert_code_blocks('No code here, move along!')
except:
self.fail("insert_code_blocks() threw an exception with a blank block, "
"or a code block with non-code text.")
Loading