]> git.gir.st - subscriptionfeed.git/blob - app/reddit/__init__.py
move reddit to seperate blueprint
[subscriptionfeed.git] / app / reddit / __init__.py
1 import re
2 import time
3 import sqlite3
4 import requests
5 #from flask_login import current_user, login_required
6 from flask_login import LoginManager, UserMixin, current_user, login_user, logout_user, login_required
7 from flask import Blueprint, render_template, request, redirect, flash, url_for, jsonify, g
8
9 from ..common.common import *
10
11 frontend = Blueprint('reddit', __name__,
12 template_folder='templates',
13 static_folder='static',
14 static_url_path='/static/rd')
15
16 @frontend.route('/feed/subreddits')
17 # disabled for guest user: @login_required
18 def feed():
19 return "reddit feed: TODO"
20 if current_user.is_anonymous:
21 token = 'guest'
22 else:
23 token = current_user.token
24 page = int(request.args.get('page', 0))
25 with sqlite3.connect(cf['global']['database']) as conn:
26 c = conn.cursor()
27 c.execute("""
28 SELECT videos.id, channel_id, name, title, published, flags.display
29 FROM videos
30 JOIN channels ON videos.channel_id = channels.id
31 LEFT JOIN flags ON (videos.id = flags.video_id) AND (flags.user = ?)
32 WHERE channel_id IN
33 (SELECT channel_id FROM subscriptions WHERE user = ?)
34 AND flags.display IS NOT 'hidden'
35 ORDER BY (display = 'pinned') DESC, crawled DESC
36 LIMIT 36
37 OFFSET 36*?""", (token, token, page))
38 rows = [{
39 'video_id': video_id,
40 'channel_id': channel_id,
41 'author': author,
42 'title': title,
43 'published': published,
44 'pinned': display == 'pinned',
45 } for (video_id, channel_id, author, title, published, display) in c.fetchall()]
46 return render_template('index.html.j2', rows=rows, page=page)
47
48 @frontend.route('/manage/subreddits')
49 # disabled for guest user: @login_required
50 def subscription_manager():
51 return "reddit feed: TODO"
52 if current_user.is_anonymous:
53 token = 'guest'
54 else:
55 token = current_user.token
56 with sqlite3.connect(cf['global']['database']) as conn:
57 #with conn.cursor() as c:
58 c = conn.cursor()
59 c.execute("""
60 SELECT subscriptions.channel_id, name,
61 (subscribed_until < datetime('now')) AS obsolete
62 FROM subscriptions
63 left JOIN channels ON channels.id = subscriptions.channel_id
64 left JOIN websub ON channels.id = websub.channel_id
65 WHERE user = ?
66 AND subscriptions.type IN ('channel', 'playlist')
67 ORDER BY obsolete=0, name COLLATE NOCASE ASC""", (token,))
68 rows = [{
69 'channel_id': channel_id,
70 'author': author or channel_id,
71 'subscribed_until': subscribed_until
72 } for (channel_id, author, subscribed_until) in c.fetchall()]
73 return render_template('subscription_manager.html.j2', rows=rows)
74
75 @frontend.route('/feed/subreddits', methods=['POST'])
76 @login_required
77 def feed_post():
78 return "reddit feed: TODO"
79 token = current_user.token
80 action = next(request.form.keys(), None)
81 if action in ['pin', 'unpin', 'hide']:
82 video_id = request.form.get(action)
83 display = {
84 'pin': 'pinned',
85 'unpin': None,
86 'hide': 'hidden',
87 }[action]
88 with sqlite3.connect(cf['global']['database']) as conn:
89 #with conn.cursor() as c:
90 c = conn.cursor()
91 c.execute("""
92 INSERT OR REPLACE INTO flags (user, video_id, display)
93 VALUES (?, ?, ?)
94 """, (token, video_id, display))
95 else:
96 flash("unsupported action", "error")
97 return redirect(request.url, code=303)
98
99 @frontend.route('/manage/subreddits', methods=['POST'])
100 @login_required
101 def manage_subscriptions():
102 return "reddit feed: TODO"
103 token = current_user.token
104 if 'subscribe' in request.form:
105 channel_id = request.form.get("subscribe")
106 match = re.search(r"(UC[A-Za-z0-9_-]{22})", channel_id)
107 if match:
108 channel_id = match.group(1)
109 else:
110 match = re.search(r"((?:PL|LL|EC|UU|FL|UL|OL)[A-Za-z0-9_-]{10,})", channel_id)
111 if match: # NOTE: PL-playlists are 32chars, others differ in length.
112 flash("playlists not (yet?) supported.", "error")
113 return redirect(request.url, code=303) # TODO: dedup redirection
114 else:
115 flash("not a valid/subscribable URI", "error")
116 return redirect(request.url, code=303) # TODO: dedup redirection
117 with sqlite3.connect(cf['global']['database']) as conn:
118 #with conn.cursor() as c:
119 c = conn.cursor()
120 c.execute("""
121 INSERT OR IGNORE INTO subscriptions (user, channel_id)
122 VALUES (?, ?)
123 """, (token, channel_id))
124 # TODO: sql-error-handling, asynchronically calling update-subs.pl
125
126 elif 'unsubscribe' in request.form:
127 channel_id = request.form.get("unsubscribe")
128 with sqlite3.connect(cf['global']['database']) as conn:
129 #with conn.cursor() as c:
130 c = conn.cursor()
131 c.execute("""
132 DELETE FROM subscriptions
133 WHERE user = ? AND channel_id = ?
134 """, (token, channel_id))
135 # TODO: sql-error-handling, report success
136
137 else:
138 flash("unsupported action", "error")
139
140 return redirect(request.url, code=303)
141
142 @frontend.route('/r/')
143 def reddit_index():
144 return ""
145 @frontend.route('/r/<subreddit>')
146 def reddit(subreddit="videos"):
147 count = int(request.args.get('count', 0))
148 before = request.args.get('before')
149 after = request.args.get('after')
150 query = '&'.join([f"{k}={v}" for k,v in [('count',count), ('before',before), ('after',after)] if v])
151 r = requests.get(f"https://old.reddit.com/r/{subreddit}.json?{query}", headers={'User-Agent':'Mozilla/5.0'})
152 if not r.ok or not 'data' in r.json():
153 return r.text+"error retrieving reddit data", 502
154
155 good = [e for e in r.json()['data']['children'] if e['data']['score'] > 1]
156 bad = [e for e in r.json()['data']['children'] if e['data']['score'] <=1]
157 videos = []
158 for entry in (good+bad):
159 e = entry['data']
160 if e['domain'] not in ['youtube.com', 'youtu.be', 'invidio.us']:
161 continue
162 video_id = re.match(r'^https?://(?:www.|m.)?(?:youtube.com/watch\?(?:.*&amp;)?v=|youtu.be/|youtube.com/embed/)([-_0-9A-Za-z]+)', e['url']).group(1)
163 if not video_id: continue
164 videos.append({
165 'video_id': video_id,
166 'title': e['title'],
167 'url': e['permalink'],
168 'n_comments': e['num_comments'],
169 'n_karma': e['score'],
170 })
171 before = r.json()['data']['before']
172 after = r.json()['data']['after']
173 return render_template('reddit.html.j2', subreddit=subreddit, rows=videos, before=before, after=after, count=count)
Imprint / Impressum