Saved posts + YT search + YT follow manager

This commit is contained in:
pluja 2020-07-29 11:04:00 +02:00
parent 9f4cf189c7
commit 14392660ff
9 changed files with 162 additions and 10 deletions

View File

@ -1 +1 @@
{"twitter": [{"username": "aantonop"}, {"username": "Trezor"}, {"username": "aitor13023985"}, {"username": "guaridadelzorro"}, {"username": "elonmusk"}, {"username": "bitcoin"}, {"username": "monero"}, {"username": "xmroutreach"}, {"username": "Locha_io"}, {"username": "randybrito"}, {"username": "btcven"}, {"username": "Snowden"}, {"username": "_prestwich"}, {"username": "TradeOnFire"}], "youtube": [{"channelId": "UCjr2bPAyPV7t35MvcgT3W8Q"}, {"channelId": "UCJWCJCWOxBYSi5DhCieLOLQ"}, {"channelId": "UCW3iqZr2cQFYKdO9Kpa97Yw"}, {"channelId": "UCLXo7UDZvByw2ixzpQCufnA"}, {"channelId": "UCR9sFzaG9Ia_kXJhfxtFMBA"}, {"channelId": "UCbdSYaPD-lr1kW27UJuk8Pw"}, {"channelId": "UCa3DVlGH2_QhvwuWlPa6MDQ"}, {"channelId": "UComoqWnjQlH7JpvqfyGnWNA"}, {"channelId": "UCA58hhLv4pdgDjBW5oNSklA"}]}
{"twitter": [{"username": "aantonop"}, {"username": "Trezor"}, {"username": "aitor13023985"}, {"username": "guaridadelzorro"}, {"username": "elonmusk"}, {"username": "bitcoin"}, {"username": "monero"}, {"username": "xmroutreach"}, {"username": "Locha_io"}, {"username": "randybrito"}, {"username": "btcven"}, {"username": "Snowden"}, {"username": "_prestwich"}, {"username": "TradeOnFire"}], "youtube": [{"channelId": "UCjr2bPAyPV7t35MvcgT3W8Q"}, {"channelId": "UCJWCJCWOxBYSi5DhCieLOLQ"}, {"channelId": "UCW3iqZr2cQFYKdO9Kpa97Yw"}, {"channelId": "UCLXo7UDZvByw2ixzpQCufnA"}, {"channelId": "UCR9sFzaG9Ia_kXJhfxtFMBA"}, {"channelId": "UCbdSYaPD-lr1kW27UJuk8Pw"}, {"channelId": "UCa3DVlGH2_QhvwuWlPa6MDQ"}, {"channelId": "UComoqWnjQlH7JpvqfyGnWNA"}, {"channelId": "UCA58hhLv4pdgDjBW5oNSklA"}, {"channelId": "UCkHR9m-tscD3ojD7_viIfTA"}, {"channelId": "UCYO_jab_esuFRV4b17AJtAw"}, {"channelId": "UC9-y-6csu5WGm29I7JiwpnA"}, {"channelId": "UC2PA-AKmVpU6NKCGtZq_rKQ"}, {"channelId": "UC2Qc22WUjL_GbBDIPvmHWmQ"}, {"channelId": "UC3Hx81QYLoEQkm3vyl4N4eQ"}, {"channelId": "UCiwy9Lx6h1Oi-UYwYDbgBZA"}, {"channelId": "UCHW_zn-nX5nvMjEA6mtNZ1A"}]}

View File

@ -15,8 +15,8 @@ class SearchForm(FlaskForm):
submit = SubmitField('Search')
class ChannelForm(FlaskForm):
channelId = StringField('Channel ID')
submit = SubmitField('Follow')
channelId = StringField('')
submit = SubmitField('Search')
class RegistrationForm(FlaskForm):

View File

@ -28,7 +28,8 @@ class User(UserMixin, db.Model):
def check_password(self, password):
return check_password_hash(self.password_hash, password)
# TWITTER
def follow(self, user):
if not self.is_following(user):
self.followed.append(user)
@ -46,9 +47,21 @@ class User(UserMixin, db.Model):
def saved_posts(self):
return Post.query.filter_by(user_id=self.id)
# YOUTUBE
def youtube_following_list(self):
return self.youtubeFollowed.all()
def is_following_yt(self, cid):
temp_cid = invidiousFollow.query.filter_by(channelId = cid).first()
if temp_cid is None:
return False
else:
following = self.youtube_following_list()
for f in following:
if f.channelId == cid:
return True
return False
followed = db.relationship(
'User', secondary=followers,
@ -88,6 +101,7 @@ class invidiousPost():
videoThumb = '#'
description = "LOREM IPSUM"
date = 'None'
views = 'NaN'
class invidiousFollow(db.Model):

View File

@ -146,6 +146,29 @@ def invidious():
videos.sort(key=lambda x: x.date, reverse=True)
return render_template('invidious.html', videos=videos, form=form)
@app.route('/ytsearch', methods=['GET', 'POST'])
@login_required
def ytsearch():
form = ChannelForm()
button_form = EmptyForm()
if form.validate_on_submit():
channelId = form.channelId.data
r = requests.get('https://invidio.us/api/v1/search?type=channel&q={}'.format(channelId))
if r.status_code == 200:
results = json.loads(r.content)
channels = []
for res in results:
channels.append({
'username':res['author'],
'channelId':res['authorId'],
'thumbnail':res['authorThumbnails'][0]['url'],
'subCount':letterify(res['subCount'])
})
return render_template('ytsearch.html', form=form, btform=button_form, results=channels)
else:
return render_template('ytsearch.html', form=form)
@app.route('/savePost/<url>', methods=['POST'])
@login_required
def savePost(url):
@ -181,6 +204,43 @@ def deleteSaved(id):
db.session.commit()
return redirect(url_for('saved'))
@app.route('/ytfollow/<channelId>', methods=['POST'])
@login_required
def ytfollow(channelId):
form = EmptyForm()
if form.validate_on_submit():
channel = invidiousFollow.query.filter_by(channelId=channelId).first()
if requests.get('https://invidio.us/feed/channel/{}'.format(channelId)).status_code == 200:
if channel is None:
follow = invidiousFollow()
follow.channelId = channelId
follow.followers.append(current_user)
try:
db.session.add(follow)
db.session.commit()
except:
flash("Something went wrong. Try again!")
return redirect(url_for('invidious'))
flash('You are following {}!'.format(channelId))
else:
flash("Something went wrong... try again")
return redirect(url_for('ytsearch'))
else:
return redirect(url_for('ytsearch'))
@app.route('/ytunfollow/<channelId>', methods=['POST'])
@login_required
def ytunfollow(channelId):
form = EmptyForm()
channel = invidiousFollow.query.filter_by(channelId=channelId).first()
try:
db.session.delete(channel)
db.session.commit()
flash("User unfollowed!")
except:
flash("There was an error unfollowing the user. Try again.")
return redirect(url_for('ytsearch'))
@app.route('/follow/<username>', methods=['POST'])
@login_required
def follow(username):
@ -412,7 +472,27 @@ def getInvidiousPosts(ids):
video.videoUrl = vid.link
video.videoTitle = vid.title
video.videoThumb = vid.media_thumbnail[0]['url']
video.views = vid.media_statistics['views']
video.description = vid.summary.split('<p style="word-break:break-word;white-space:pre-wrap">')[1]
video.description = re.sub(r'^https?:\/\/.*[\r\n]*', '', video.description[0:120]+"...", flags=re.MULTILINE)
videos.append(video)
return videos
return videos
def letterify(number):
order = len(str(number))
if order == 4:
subCount = "{k}.{c}k".format(k=str(number)[0:1], c=str(number)[1:2])
elif order == 5:
subCount = "{k}.{c}k".format(k=str(number)[0:2], c=str(number)[2:3])
elif order == 6:
subCount = "{k}.{c}k".format(k=str(number)[0:3], c=str(number)[3:4])
elif order == 7:
subCount = "~{M}M".format(M=str(number)[0:1])
elif order == 8:
subCount = "~{M}M".format(M=str(number)[0:2])
elif order >= 8:
subCount = "{M}M".format(M=str(number)[0:3])
else:
subCount = str(number)
return subCount

View File

@ -20,7 +20,7 @@
</div>
<div class="extra content">
<p>
<form class="ui form" action="{{ url_for('savePost', url=post.urlToPost.replace('/', '~')) }}" method="post">
<form class="ui form" action="{{ url_for('savePost', url=post.url.replace('/', '~')) }}" method="post">
<button type="submit" class="ui icon button">
<i class="bookmark outline icon"></i>
</button>

View File

@ -21,7 +21,7 @@
<p>{{post.content}}</p>
</div>
<div class="extra content">
<form class="ui form" action="{{ url_for('savePost', url=post.urlToPost.replace('/', '~')) }}" method="post">
<form class="ui form" action="{{ url_for('savePost', url=post.url.replace('/', '~')) }}" method="post">
<button type="submit" class="ui icon button">
<i class="bookmark outline icon"></i>
</button>

View File

@ -12,13 +12,17 @@
</div>
</div>
<div class="extra content">
<span class="right floated">
<i class="eye icon"></i>
{{video.views}}
</span>
<span class="right floated">
<i class="clock icon"></i>
{{video.timeStamp}}
{{video.timeStamp}}
</span>
<span>
<a href="{{video.videoUrl}}">
<i class="eye icon"></i>
<i class="share square outline icon"></i>
Open
</a>
</span>

View File

@ -38,6 +38,7 @@
<a href="{{ url_for('following') }}" class="twitter item">Following</a>
<a href="{{ url_for('saved') }}" class="twitter item">Saved</a>
<a href="{{ url_for('invidious') }}" class="youtube item">Youtube</a>
<a href="{{ url_for('ytsearch') }}" class="youtube item">Search</a>
<a href="{{ url_for('logout') }}" class="item">Logout</a>
<a href="{{ url_for('settings') }}" class="item"><i class="cog icon"></i></a>
{% endif %}

View File

@ -0,0 +1,53 @@
{% extends "base.html" %}
{% block content %}
<div class="ui one column centered grid">
<form class="ui form" action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.channelId.label }}<br>
{{ form.channelId(size=32) }}<br>
{% for error in form.channelId.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit() }}</p>
</form>
{% if results %}
<div class="ui one column centered grid">
<div class="ui middle aligned divided list">
{% for res in results %}
<div class="item">
<div class="right floated content">
{% if not current_user.is_following_yt(res.channelId) %}
<p>
<form action="{{ url_for('ytfollow', channelId=res.channelId) }}" method="post">
{{ btform.hidden_tag() }}
{{ btform.submit(value='Follow') }}
</form>
</p>
{% else %}
<p>
<form action="{{ url_for('ytunfollow', channelId=res.channelId) }}" method="post">
{{ btform.hidden_tag() }}
{{ btform.submit(value='Unfollow') }}
</form>
</p>
{% endif %}
</div>
<img class="ui avatar image" src="{{ res.thumbnail }}">
<div class="content">
{{res.username}}
<div class="ui label">
<i class="user icon"></i> {{res.subCount}}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endblock %}