##// END OF EJS Templates
Fixed image search by google. Added duplicates search for images
neko259 -
r1802:5f0f8146 default
parent child Browse files
Show More
@@ -1,45 +1,48 b''
1 [Version]
1 [Version]
2 Version = 4.0.0 2017
2 Version = 4.0.0 2017
3 SiteName = Neboard DEV
3 SiteName = Neboard DEV
4
4
5 [Cache]
5 [Cache]
6 # Timeout for caching, if cache is used
6 # Timeout for caching, if cache is used
7 CacheTimeout = 600
7 CacheTimeout = 600
8
8
9 [Forms]
9 [Forms]
10 # Max post length in characters
10 # Max post length in characters
11 MaxTextLength = 30000
11 MaxTextLength = 30000
12 MaxFileSize = 8000000
12 MaxFileSize = 8000000
13 LimitFirstPosting = true
13 LimitFirstPosting = true
14 LimitPostingSpeed = false
14 LimitPostingSpeed = false
15 PowDifficulty = 0
15 PowDifficulty = 0
16 # Delay in seconds
16 # Delay in seconds
17 PostingDelay = 30
17 PostingDelay = 30
18 Autoban = false
18 Autoban = false
19 DefaultTag = test
19 DefaultTag = test
20 MaxFileCount = 1
20 MaxFileCount = 1
21
21
22 [Messages]
22 [Messages]
23 # Thread bumplimit
23 # Thread bumplimit
24 MaxPostsPerThread = 10
24 MaxPostsPerThread = 10
25 ThreadArchiveDays = 300
25 ThreadArchiveDays = 300
26 AnonymousMode = false
26 AnonymousMode = false
27
27
28 [View]
28 [View]
29 DefaultTheme = md
29 DefaultTheme = md
30 DefaultImageViewer = simple
30 DefaultImageViewer = simple
31 LastRepliesCount = 3
31 LastRepliesCount = 3
32 ThreadsPerPage = 3
32 ThreadsPerPage = 3
33 PostsPerPage = 10
33 PostsPerPage = 10
34 ImagesPerPageGallery = 20
34 ImagesPerPageGallery = 20
35 MaxFavoriteThreads = 20
35 MaxFavoriteThreads = 20
36 MaxLandingThreads = 20
36 MaxLandingThreads = 20
37 Themes=md:Mystic Dark,md_centered:Mystic Dark (centered),sw:Snow White,pg:Photon Grey,ad:Amanita Dark,iw:Inocibe White
37 Themes=md:Mystic Dark,md_centered:Mystic Dark (centered),sw:Snow White,pg:Photon Grey,ad:Amanita Dark,iw:Inocibe White
38 ImageViewers=simple:Simple,popup:Popup
38 ImageViewers=simple:Simple,popup:Popup
39
39
40 [Storage]
40 [Storage]
41 # Enable archiving threads instead of deletion when the thread limit is reached
41 # Enable archiving threads instead of deletion when the thread limit is reached
42 ArchiveThreads = true
42 ArchiveThreads = true
43
43
44 [RSS]
44 [RSS]
45 MaxItems = 20
45 MaxItems = 20
46
47 [External]
48 ImageSearchHost=http://127.0.0.1/
@@ -1,39 +1,40 b''
1 {% extends "boards/thread.html" %}
1 {% extends "boards/thread.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load static from staticfiles %}
4 {% load static from staticfiles %}
5 {% load board %}
5 {% load board %}
6 {% load tz %}
6 {% load tz %}
7
7
8 {% block head %}
8 {% block head %}
9 <meta name="robots" content="noindex">
9 <meta name="robots" content="noindex">
10 <title>{{ thread.get_opening_post.get_title|striptags|truncatewords:10 }}
10 <title>{{ thread.get_opening_post.get_title|striptags|truncatewords:10 }}
11 - {{ site_name }}</title>
11 - {{ site_name }}</title>
12 {% endblock %}
12 {% endblock %}
13
13
14 {% block thread_content %}
14 {% block thread_content %}
15 {% get_current_language as LANGUAGE_CODE %}
15 {% get_current_language as LANGUAGE_CODE %}
16 {% get_current_timezone as TIME_ZONE %}
16 {% get_current_timezone as TIME_ZONE %}
17
17
18 <div id="posts-table">
18 <div id="posts-table">
19 {% if posts %}
19 {% if posts %}
20 {% for post in posts %}
20 {% for post in posts %}
21 {% for image in post.get_images %}
21 {% for image in post.get_images %}
22 <div class="gallery_image">
22 <div class="gallery_image">
23 {% autoescape off %}
23 {% autoescape off %}
24 {{ image.get_view }}
24 {{ image.get_view }}
25 <div class="gallery_image_metadata">
25 <div class="gallery_image_metadata">
26 {{ image.get_size.0 }}x{{ image.get_size.1 }}
26 {{ image.get_size.0 }}x{{ image.get_size.1 }}
27 {% image_actions image.file.url request.get_host %}
27 {% image_actions image.file.url %},
28 [<a href="{% url 'feed' %}?image_hash={{ image.hash }}">{{ site_name }}</a>]
28 <br />
29 <br />
29 <a href="{{ post.get_absolute_url }}">>>{{ post.id }}</a>
30 <a href="{{ post.get_absolute_url }}">>>{{ post.id }}</a>
30 </div>
31 </div>
31 {% endautoescape %}
32 {% endautoescape %}
32 </div>
33 </div>
33 {% endfor %}
34 {% endfor %}
34 {% endfor %}
35 {% endfor %}
35 {% else %}
36 {% else %}
36 {% trans 'No images.' %}
37 {% trans 'No images.' %}
37 {% endif %}
38 {% endif %}
38 </div>
39 </div>
39 {% endblock %}
40 {% endblock %}
@@ -1,119 +1,123 b''
1 import re
1 import re
2
2
3 from django.shortcuts import get_object_or_404
3 from django.shortcuts import get_object_or_404
4 from django import template
4 from django import template
5 from django.utils.text import re_tag
5 from django.utils.text import re_tag
6 from django.core.urlresolvers import reverse
6
7
7 from boards.mdx_neboard import LINE_BREAK_HTML
8 from boards.mdx_neboard import LINE_BREAK_HTML
9 from boards import settings
8
10
9
11
10 IMG_ACTION_URL = '[<a href="{}">{}</a>]'
12 IMG_ACTION_URL = '[<a href="{}">{}</a>]'
11 REGEX_NEWLINE = re.compile(LINE_BREAK_HTML)
13 REGEX_NEWLINE = re.compile(LINE_BREAK_HTML)
12 TRUNCATOR = '...'
14 TRUNCATOR = '...'
13 HTML4_SINGLETS =(
15 HTML4_SINGLETS =(
14 'br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input'
16 'br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input'
15 )
17 )
16
18
17
19
18 register = template.Library()
20 register = template.Library()
19
21
20 actions = [
22 actions = [
21 {
23 {
22 'name': 'google',
24 'name': 'google',
23 'link': 'http://google.com/searchbyimage?image_url=%s',
25 'link': 'https://www.google.com/searchbyimage?image_url={}',
24 },
26 },
25 {
27 {
26 'name': 'iqdb',
28 'name': 'iqdb',
27 'link': 'http://iqdb.org/?url=%s',
29 'link': 'http://iqdb.org/?url={}',
28 },
30 },
29 ]
31 ]
30
32
31
33
32 @register.simple_tag(name='post_url')
34 @register.simple_tag(name='post_url')
33 def post_url(*args, **kwargs):
35 def post_url(*args, **kwargs):
34 post_id = args[0]
36 post_id = args[0]
35
37
36 post = get_object_or_404('Post', id=post_id)
38 post = get_object_or_404('Post', id=post_id)
37
39
38 return post.get_absolute_url()
40 return post.get_absolute_url()
39
41
40
42
41 @register.simple_tag(name='image_actions')
43 @register.simple_tag(name='image_actions')
42 def image_actions(*args, **kwargs):
44 def image_actions(*args, **kwargs):
43 image_link = args[0]
45 image_link = args[0]
44 if len(args) > 1:
46 host = settings.get('External', 'ImageSearchHost')
45 image_link = 'http://' + args[1] + image_link # TODO https?
47 if host.endswith('/'):
48 host = host[:-1]
49 image_link = settings.get('External', 'ImageSearchHost') + image_link
46
50
47 return ', '.join([IMG_ACTION_URL.format(
51 return ', '.join([IMG_ACTION_URL.format(
48 action['link'] % image_link, action['name']) for action in actions])
52 action['link'].format(image_link), action['name']) for action in actions])
49
53
50
54
51 @register.inclusion_tag('boards/post.html', name='post_view', takes_context=True)
55 @register.inclusion_tag('boards/post.html', name='post_view', takes_context=True)
52 def post_view(context, post, *args, **kwargs):
56 def post_view(context, post, *args, **kwargs):
53 kwargs['perms'] = context['perms']
57 kwargs['perms'] = context['perms']
54 return post.get_view_params(*args, **kwargs)
58 return post.get_view_params(*args, **kwargs)
55
59
56
60
57 @register.simple_tag(name='page_url')
61 @register.simple_tag(name='page_url')
58 def page_url(paginator, page_number, *args, **kwargs):
62 def page_url(paginator, page_number, *args, **kwargs):
59 if paginator.supports_urls():
63 if paginator.supports_urls():
60 return paginator.get_page_url(page_number)
64 return paginator.get_page_url(page_number)
61
65
62
66
63 @register.filter(name='truncatenewlines_html')
67 @register.filter(name='truncatenewlines_html')
64 def truncatenewlines_html(value, arg):
68 def truncatenewlines_html(value, arg):
65 end_pos = 0
69 end_pos = 0
66 start_pos = 0
70 start_pos = 0
67 match_count = 0
71 match_count = 0
68
72
69 # Collect places for truncation
73 # Collect places for truncation
70 while match_count <= arg:
74 while match_count <= arg:
71 m = REGEX_NEWLINE.search(value, end_pos)
75 m = REGEX_NEWLINE.search(value, end_pos)
72 if m is None:
76 if m is None:
73 break
77 break
74 else:
78 else:
75 match_count += 1
79 match_count += 1
76 end_pos = m.end()
80 end_pos = m.end()
77 start_pos = m.start()
81 start_pos = m.start()
78
82
79 # Find and close open tags
83 # Find and close open tags
80 if match_count > arg:
84 if match_count > arg:
81 truncate_pos = start_pos
85 truncate_pos = start_pos
82
86
83 open_tags = []
87 open_tags = []
84 text = value[:truncate_pos]
88 text = value[:truncate_pos]
85 current_pos = 0
89 current_pos = 0
86 while True:
90 while True:
87 tag = re_tag.search(text, current_pos)
91 tag = re_tag.search(text, current_pos)
88 if tag is None:
92 if tag is None:
89 break
93 break
90 else:
94 else:
91 closing_tag, tagname, self_closing = tag.groups()
95 closing_tag, tagname, self_closing = tag.groups()
92 tagname = tagname.lower()
96 tagname = tagname.lower()
93 if self_closing or tagname in HTML4_SINGLETS:
97 if self_closing or tagname in HTML4_SINGLETS:
94 pass
98 pass
95 elif closing_tag:
99 elif closing_tag:
96 # Check for match in open tags list
100 # Check for match in open tags list
97 try:
101 try:
98 i = open_tags.index(tagname)
102 i = open_tags.index(tagname)
99 except ValueError:
103 except ValueError:
100 pass
104 pass
101 else:
105 else:
102 # SGML: An end tag closes, back to the matching start tag,
106 # SGML: An end tag closes, back to the matching start tag,
103 # all unclosed intervening start tags with omitted end tags
107 # all unclosed intervening start tags with omitted end tags
104 open_tags = open_tags[i + 1:]
108 open_tags = open_tags[i + 1:]
105 else:
109 else:
106 # Add it to the start of the open tags list
110 # Add it to the start of the open tags list
107 open_tags.insert(0, tagname)
111 open_tags.insert(0, tagname)
108
112
109 current_pos = tag.end()
113 current_pos = tag.end()
110
114
111 if not text.endswith(TRUNCATOR):
115 if not text.endswith(TRUNCATOR):
112 text += TRUNCATOR
116 text += TRUNCATOR
113 for tag in open_tags:
117 for tag in open_tags:
114 text += '</{}>'.format(tag)
118 text += '</{}>'.format(tag)
115 else:
119 else:
116 text = value
120 text = value
117
121
118 return text
122 return text
119
123
@@ -1,74 +1,123 b''
1 from django.core.urlresolvers import reverse
1 from django.core.urlresolvers import reverse
2 from django.shortcuts import render
2 from django.shortcuts import render
3
3
4 from boards import settings
4 from boards import settings
5 from boards.abstracts.paginator import get_paginator
5 from boards.abstracts.paginator import get_paginator
6 from boards.abstracts.settingsmanager import get_settings_manager
6 from boards.abstracts.settingsmanager import get_settings_manager
7 from boards.models import Post
7 from boards.models import Post
8 from boards.views.base import BaseBoardView
8 from boards.views.base import BaseBoardView
9 from boards.views.posting_mixin import PostMixin
9 from boards.views.posting_mixin import PostMixin
10
10
11 POSTS_PER_PAGE = settings.get_int('View', 'PostsPerPage')
11 POSTS_PER_PAGE = settings.get_int('View', 'PostsPerPage')
12
12
13 PARAMETER_CURRENT_PAGE = 'current_page'
13 PARAMETER_CURRENT_PAGE = 'current_page'
14 PARAMETER_PAGINATOR = 'paginator'
14 PARAMETER_PAGINATOR = 'paginator'
15 PARAMETER_POSTS = 'posts'
15 PARAMETER_POSTS = 'posts'
16
16
17 PARAMETER_PREV_LINK = 'prev_page_link'
17 PARAMETER_PREV_LINK = 'prev_page_link'
18 PARAMETER_NEXT_LINK = 'next_page_link'
18 PARAMETER_NEXT_LINK = 'next_page_link'
19
19
20 TEMPLATE = 'boards/feed.html'
20 TEMPLATE = 'boards/feed.html'
21 DEFAULT_PAGE = 1
21 DEFAULT_PAGE = 1
22
22
23
23
24 class FeedFilter:
25 @staticmethod
26 def get_filtered_posts(request, posts):
27 return posts
28
29
30 class TripcodeFilter(FeedFilter):
31 @staticmethod
32 def get_filtered_posts(request, posts):
33 filtered_posts = posts
34 tripcode = request.GET.get('tripcode', None)
35 if tripcode:
36 filtered_posts = filtered_posts.filter(tripcode)
37 return filtered_posts
38
39
40 class FavoritesFilter(FeedFilter):
41 @staticmethod
42 def get_filtered_posts(request, posts):
43 filtered_posts = posts
44
45 favorites = 'favorites' in request.GET
46 if favorites:
47 settings_manager = get_settings_manager(request)
48 fav_thread_ops = Post.objects.filter(id__in=settings_manager.get_fav_threads().keys())
49 fav_threads = [op.get_thread() for op in fav_thread_ops]
50 filtered_posts = filtered_posts.filter(thread__in=fav_threads)
51 return filtered_posts
52
53
54 class IpFilter(FeedFilter):
55 @staticmethod
56 def get_filtered_posts(request, posts):
57 filtered_posts = posts
58
59 ip = request.GET.get('ip', None)
60 if ip and request.user.has_perm('post_delete'):
61 filtered_posts = filtered_posts.filter(poster_ip=ip)
62 return filtered_posts
63
64
65 class HashFilter(FeedFilter):
66 @staticmethod
67 def get_filtered_posts(request, posts):
68 filtered_posts = posts
69
70 image_hash = request.GET.get('image_hash', None)
71 if image_hash:
72 filtered_posts = filtered_posts.filter(attachments__hash=image_hash)
73 return filtered_posts
74
75
24 class FeedView(PostMixin, BaseBoardView):
76 class FeedView(PostMixin, BaseBoardView):
77 filters = (
78 TripcodeFilter,
79 FavoritesFilter,
80 IpFilter,
81 HashFilter,
82 )
25
83
26 def get(self, request):
84 def get(self, request):
27 page = request.GET.get('page', DEFAULT_PAGE)
85 page = request.GET.get('page', DEFAULT_PAGE)
28 tripcode = request.GET.get('tripcode', None)
29 favorites = 'favorites' in request.GET
30 ip = request.GET.get('ip', None)
31
86
32 params = self.get_context_data(request=request)
87 params = self.get_context_data(request=request)
33
88
34 settings_manager = get_settings_manager(request)
89 settings_manager = get_settings_manager(request)
35
90
36 posts = Post.objects.exclude(
91 posts = Post.objects.exclude(
37 thread__tags__in=settings_manager.get_hidden_tags()).order_by(
92 thread__tags__in=settings_manager.get_hidden_tags()).order_by(
38 '-pub_time').prefetch_related('attachments', 'thread')
93 '-pub_time').prefetch_related('attachments', 'thread')
39 if tripcode:
94 for filter in self.filters:
40 posts = posts.filter(tripcode=tripcode)
95 posts = filter.get_filtered_posts(request, posts)
41 if favorites:
42 fav_thread_ops = Post.objects.filter(id__in=settings_manager.get_fav_threads().keys())
43 fav_threads = [op.get_thread() for op in fav_thread_ops]
44 posts = posts.filter(thread__in=fav_threads)
45 if ip and request.user.has_perm('post_delete'):
46 posts = posts.filter(poster_ip=ip)
47
96
48 paginator = get_paginator(posts, POSTS_PER_PAGE)
97 paginator = get_paginator(posts, POSTS_PER_PAGE)
49 paginator.current_page = int(page)
98 paginator.current_page = int(page)
50
99
51 params[PARAMETER_POSTS] = paginator.page(page).object_list
100 params[PARAMETER_POSTS] = paginator.page(page).object_list
52
101
53 paginator.set_url(reverse('feed'), request.GET.dict())
102 paginator.set_url(reverse('feed'), request.GET.dict())
54
103
55 self.get_page_context(paginator, params, page)
104 self.get_page_context(paginator, params, page)
56
105
57 return render(request, TEMPLATE, params)
106 return render(request, TEMPLATE, params)
58
107
59 # TODO Dedup this into PagedMixin
108 # TODO Dedup this into PagedMixin
60 def get_page_context(self, paginator, params, page):
109 def get_page_context(self, paginator, params, page):
61 """
110 """
62 Get pagination context variables
111 Get pagination context variables
63 """
112 """
64
113
65 params[PARAMETER_PAGINATOR] = paginator
114 params[PARAMETER_PAGINATOR] = paginator
66 current_page = paginator.page(int(page))
115 current_page = paginator.page(int(page))
67 params[PARAMETER_CURRENT_PAGE] = current_page
116 params[PARAMETER_CURRENT_PAGE] = current_page
68 if current_page.has_previous():
117 if current_page.has_previous():
69 params[PARAMETER_PREV_LINK] = paginator.get_page_url(
118 params[PARAMETER_PREV_LINK] = paginator.get_page_url(
70 current_page.previous_page_number())
119 current_page.previous_page_number())
71 if current_page.has_next():
120 if current_page.has_next():
72 params[PARAMETER_NEXT_LINK] = paginator.get_page_url(
121 params[PARAMETER_NEXT_LINK] = paginator.get_page_url(
73 current_page.next_page_number())
122 current_page.next_page_number())
74
123
General Comments 0
You need to be logged in to leave comments. Login now