Saved posts + YT search + YT follow manager
This commit is contained in:
parent
9f4cf189c7
commit
14392660ff
@ -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"}]}
|
@ -15,8 +15,8 @@ class SearchForm(FlaskForm):
|
|||||||
submit = SubmitField('Search')
|
submit = SubmitField('Search')
|
||||||
|
|
||||||
class ChannelForm(FlaskForm):
|
class ChannelForm(FlaskForm):
|
||||||
channelId = StringField('Channel ID')
|
channelId = StringField('')
|
||||||
submit = SubmitField('Follow')
|
submit = SubmitField('Search')
|
||||||
|
|
||||||
|
|
||||||
class RegistrationForm(FlaskForm):
|
class RegistrationForm(FlaskForm):
|
||||||
|
@ -28,7 +28,8 @@ class User(UserMixin, db.Model):
|
|||||||
|
|
||||||
def check_password(self, password):
|
def check_password(self, password):
|
||||||
return check_password_hash(self.password_hash, password)
|
return check_password_hash(self.password_hash, password)
|
||||||
|
|
||||||
|
# TWITTER
|
||||||
def follow(self, user):
|
def follow(self, user):
|
||||||
if not self.is_following(user):
|
if not self.is_following(user):
|
||||||
self.followed.append(user)
|
self.followed.append(user)
|
||||||
@ -46,9 +47,21 @@ class User(UserMixin, db.Model):
|
|||||||
|
|
||||||
def saved_posts(self):
|
def saved_posts(self):
|
||||||
return Post.query.filter_by(user_id=self.id)
|
return Post.query.filter_by(user_id=self.id)
|
||||||
|
|
||||||
|
# YOUTUBE
|
||||||
def youtube_following_list(self):
|
def youtube_following_list(self):
|
||||||
return self.youtubeFollowed.all()
|
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(
|
followed = db.relationship(
|
||||||
'User', secondary=followers,
|
'User', secondary=followers,
|
||||||
@ -88,6 +101,7 @@ class invidiousPost():
|
|||||||
videoThumb = '#'
|
videoThumb = '#'
|
||||||
description = "LOREM IPSUM"
|
description = "LOREM IPSUM"
|
||||||
date = 'None'
|
date = 'None'
|
||||||
|
views = 'NaN'
|
||||||
|
|
||||||
|
|
||||||
class invidiousFollow(db.Model):
|
class invidiousFollow(db.Model):
|
||||||
|
@ -146,6 +146,29 @@ def invidious():
|
|||||||
videos.sort(key=lambda x: x.date, reverse=True)
|
videos.sort(key=lambda x: x.date, reverse=True)
|
||||||
return render_template('invidious.html', videos=videos, form=form)
|
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'])
|
@app.route('/savePost/<url>', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def savePost(url):
|
def savePost(url):
|
||||||
@ -181,6 +204,43 @@ def deleteSaved(id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for('saved'))
|
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'])
|
@app.route('/follow/<username>', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def follow(username):
|
def follow(username):
|
||||||
@ -412,7 +472,27 @@ def getInvidiousPosts(ids):
|
|||||||
video.videoUrl = vid.link
|
video.videoUrl = vid.link
|
||||||
video.videoTitle = vid.title
|
video.videoTitle = vid.title
|
||||||
video.videoThumb = vid.media_thumbnail[0]['url']
|
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 = 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)
|
video.description = re.sub(r'^https?:\/\/.*[\r\n]*', '', video.description[0:120]+"...", flags=re.MULTILINE)
|
||||||
videos.append(video)
|
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
|
@ -20,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="extra content">
|
<div class="extra content">
|
||||||
<p>
|
<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">
|
<button type="submit" class="ui icon button">
|
||||||
<i class="bookmark outline icon"></i>
|
<i class="bookmark outline icon"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<p>{{post.content}}</p>
|
<p>{{post.content}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="extra content">
|
<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">
|
<button type="submit" class="ui icon button">
|
||||||
<i class="bookmark outline icon"></i>
|
<i class="bookmark outline icon"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -12,13 +12,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="extra content">
|
<div class="extra content">
|
||||||
|
<span class="right floated">
|
||||||
|
<i class="eye icon"></i>
|
||||||
|
{{video.views}}
|
||||||
|
</span>
|
||||||
<span class="right floated">
|
<span class="right floated">
|
||||||
<i class="clock icon"></i>
|
<i class="clock icon"></i>
|
||||||
{{video.timeStamp}}
|
{{video.timeStamp}}
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<a href="{{video.videoUrl}}">
|
<a href="{{video.videoUrl}}">
|
||||||
<i class="eye icon"></i>
|
<i class="share square outline icon"></i>
|
||||||
Open
|
Open
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
<a href="{{ url_for('following') }}" class="twitter item">Following</a>
|
<a href="{{ url_for('following') }}" class="twitter item">Following</a>
|
||||||
<a href="{{ url_for('saved') }}" class="twitter item">Saved</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('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('logout') }}" class="item">Logout</a>
|
||||||
<a href="{{ url_for('settings') }}" class="item"><i class="cog icon"></i></a>
|
<a href="{{ url_for('settings') }}" class="item"><i class="cog icon"></i></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
53
app/templates/ytsearch.html
Normal file
53
app/templates/ytsearch.html
Normal 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 %}
|
Reference in New Issue
Block a user