Efficiency improvements + Pinned posts.
This commit is contained in:
parent
adf57e8ca9
commit
6892d41c52
@ -56,14 +56,16 @@ def load_user(id):
|
|||||||
class twitterPost():
|
class twitterPost():
|
||||||
date = 0
|
date = 0
|
||||||
username = 'Error'
|
username = 'Error'
|
||||||
|
twitterName = "Error Name"
|
||||||
|
isPinned = False
|
||||||
op = 'Error'
|
op = 'Error'
|
||||||
isRT = True
|
isRT = True
|
||||||
urlToPost = ""
|
urlToPost = ""
|
||||||
validPost = True
|
validPost = True
|
||||||
content = "El gato siguió a la liebre. Esto es un texto de ejemplo."
|
content = "El gato siguió a la liebre. Esto es un texto de ejemplo."
|
||||||
profilePic = "url"
|
profilePic = "url"
|
||||||
twitterName = "Error Name"
|
|
||||||
timeStamp = "error"
|
timeStamp = "error"
|
||||||
|
userProfilePic = "1.png"
|
||||||
|
|
||||||
class Post(db.Model):
|
class Post(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
114
app/routes.py
114
app/routes.py
@ -13,7 +13,6 @@ import requests
|
|||||||
|
|
||||||
nitterInstance = "https://nitter.net/"
|
nitterInstance = "https://nitter.net/"
|
||||||
nitterInstanceII = "https://nitter.mastodont.cat"
|
nitterInstanceII = "https://nitter.mastodont.cat"
|
||||||
print("[ATTENTION]: New version. You will need to install BeautifulSoup: 'pip install bs4'")
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@app.route('/index')
|
@app.route('/index')
|
||||||
@ -24,39 +23,9 @@ def index():
|
|||||||
posts = []
|
posts = []
|
||||||
avatarPath = "img/avatars/1.png"
|
avatarPath = "img/avatars/1.png"
|
||||||
form = EmptyForm()
|
form = EmptyForm()
|
||||||
for fwd in following:
|
[posts.extend(getPosts(fwd.username)) for fwd in following]
|
||||||
avatarPath = "img/avatars/{}.png".format(str(random.randint(1,12)))
|
posts.sort(key=lambda x: x.timeStamp, reverse=True)
|
||||||
|
return render_template('index.html', title='Home', posts=posts, avatar=avatarPath, followedCount=followed, form=form)
|
||||||
#Gather profile info.
|
|
||||||
rssFeed = feedparser.parse('{instance}{user}/rss'.format(instance=nitterInstance, user=fwd.username))
|
|
||||||
twitterAt = rssFeed.feed.title.split("/")[1].replace(" ", "")
|
|
||||||
twitterName = rssFeed.feed.title.split("/")[0]
|
|
||||||
|
|
||||||
#Gather posts
|
|
||||||
if rssFeed.entries != []:
|
|
||||||
for post in rssFeed.entries:
|
|
||||||
newPost = twitterPost()
|
|
||||||
|
|
||||||
newPost.username = rssFeed.feed.title.split("/")[0]
|
|
||||||
newPost.date = getTimeDiff(post.published_parsed)
|
|
||||||
newPost.timeStamp = datetime.datetime(*post.published_parsed[:6])
|
|
||||||
newPost.op = post.author
|
|
||||||
newPost.urlToPost = post.link
|
|
||||||
newPost.content = Markup(post.description)
|
|
||||||
|
|
||||||
if "RT by" in post.title:
|
|
||||||
newPost.isRT = True
|
|
||||||
newPost.profilePic = ""
|
|
||||||
else:
|
|
||||||
newPost.isRT = False
|
|
||||||
try:
|
|
||||||
newPost.profilePic = rssFeed.channel.image.url
|
|
||||||
except:
|
|
||||||
newPost.profilePic = avatarPath
|
|
||||||
posts.append(newPost)
|
|
||||||
posts.sort(key=lambda x: x.timeStamp, reverse=True)
|
|
||||||
return render_template('index.html', title='Home', posts=posts, avatar=avatarPath, followedCount=followed, twitterAt=twitterAt, twitterName=twitterName, form=form)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/login', methods=['GET', 'POST'])
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
def login():
|
def login():
|
||||||
@ -188,7 +157,7 @@ def search():
|
|||||||
user = form.username.data
|
user = form.username.data
|
||||||
if isTwitterUser(user):
|
if isTwitterUser(user):
|
||||||
r = requests.get("{instance}search?f=users&q={usern}".format(instance=nitterInstance, usern=user))
|
r = requests.get("{instance}search?f=users&q={usern}".format(instance=nitterInstance, usern=user))
|
||||||
html = BeautifulSoup(str(r.content), features="lxml")
|
html = BeautifulSoup(str(r.content), "lxml")
|
||||||
results = html.body.find_all('a', attrs={'class':'tweet-link'})
|
results = html.body.find_all('a', attrs={'class':'tweet-link'})
|
||||||
|
|
||||||
parsedResults = [s['href'].replace("/", "") for s in results]
|
parsedResults = [s['href'].replace("/", "") for s in results]
|
||||||
@ -221,42 +190,11 @@ def user(username):
|
|||||||
elif not isTwitter and user is None:
|
elif not isTwitter and user is None:
|
||||||
return redirect(url_for('notfound'))
|
return redirect(url_for('notfound'))
|
||||||
|
|
||||||
#Gather profile info.
|
|
||||||
rssFeed = feedparser.parse('{instance}{user}/rss'.format(instance=nitterInstance,user=username))
|
|
||||||
try:
|
|
||||||
profilePicture = rssFeed.channel.image.url
|
|
||||||
except:
|
|
||||||
profilePicture = ""
|
|
||||||
twitterAt = rssFeed.feed.title.split("/")[1].replace(" ", "")
|
|
||||||
twitterName = rssFeed.feed.title.split("/")[0]
|
|
||||||
|
|
||||||
#Gather posts
|
|
||||||
posts = []
|
posts = []
|
||||||
for post in rssFeed.entries:
|
posts.extend(getPosts(username))
|
||||||
newPost = twitterPost()
|
|
||||||
newPost.username = rssFeed.feed.title.split("/")[0]
|
|
||||||
newPost.date = getTimeDiff(post.published_parsed)
|
|
||||||
newPost.timeStamp = datetime.datetime(*post.published_parsed[:6])
|
|
||||||
newPost.op = post.author
|
|
||||||
newPost.urlToPost = post.link
|
|
||||||
newPost.content = Markup(post.description)
|
|
||||||
|
|
||||||
if "RT by" in post.title:
|
|
||||||
newPost.isRT = True
|
|
||||||
newPost.profilePic = ""
|
|
||||||
else:
|
|
||||||
newPost.isRT = False
|
|
||||||
try:
|
|
||||||
newPost.profilePic = rssFeed.channel.image.url
|
|
||||||
except:
|
|
||||||
newPost.profilePic = avatarPath
|
|
||||||
|
|
||||||
#validPost = True
|
|
||||||
posts.append(newPost)
|
|
||||||
|
|
||||||
form = EmptyForm()
|
form = EmptyForm()
|
||||||
user = User.query.filter_by(username=username).first()
|
user = User.query.filter_by(username=username).first()
|
||||||
return render_template('user.html', user=user, posts=posts, form=form, profilePic=profilePicture, twitterAt=twitterAt, twitterName=twitterName)
|
return render_template('user.html', user=user, posts=posts, form=form)
|
||||||
|
|
||||||
def getTimeDiff(t):
|
def getTimeDiff(t):
|
||||||
tweetTime = datetime.datetime(*t[:6])
|
tweetTime = datetime.datetime(*t[:6])
|
||||||
@ -273,7 +211,43 @@ def getTimeDiff(t):
|
|||||||
|
|
||||||
def isTwitterUser(username):
|
def isTwitterUser(username):
|
||||||
request = requests.get('https://nitter.net/{}'.format(username), timeout=1)
|
request = requests.get('https://nitter.net/{}'.format(username), timeout=1)
|
||||||
print("User {name} is {boo} twitter.".format(name=username, boo=request.status_code == 404))
|
|
||||||
if request.status_code == 404:
|
if request.status_code == 404:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def getPosts(account):
|
||||||
|
avatarPath = "img/avatars/{}.png".format(str(random.randint(1,12)))
|
||||||
|
posts = []
|
||||||
|
|
||||||
|
#Gather profile info.
|
||||||
|
rssFeed = feedparser.parse('{instance}{user}/rss'.format(instance=nitterInstance, user=account))
|
||||||
|
#Gather posts
|
||||||
|
if rssFeed.entries != []:
|
||||||
|
for post in rssFeed.entries:
|
||||||
|
newPost = twitterPost()
|
||||||
|
newPost.username = rssFeed.feed.title.split("/")[1].replace(" ", "")
|
||||||
|
newPost.twitterName = rssFeed.feed.title.split("/")[0]
|
||||||
|
newPost.date = getTimeDiff(post.published_parsed)
|
||||||
|
newPost.timeStamp = datetime.datetime(*post.published_parsed[:6])
|
||||||
|
newPost.op = post.author
|
||||||
|
try:
|
||||||
|
newPost.userProfilePic = rssFeed.channel.image.url
|
||||||
|
except:
|
||||||
|
newPost.profilePicture = ""
|
||||||
|
newPost.urlToPost = post.link
|
||||||
|
newPost.content = Markup(post.description)
|
||||||
|
|
||||||
|
if "Pinned" in post.title.split(":")[0]:
|
||||||
|
newPost.isPinned = True
|
||||||
|
|
||||||
|
if "RT by" in post.title:
|
||||||
|
newPost.isRT = True
|
||||||
|
newPost.profilePic = ""
|
||||||
|
else:
|
||||||
|
newPost.isRT = False
|
||||||
|
try:
|
||||||
|
newPost.profilePic = rssFeed.channel.image.url
|
||||||
|
except:
|
||||||
|
newPost.profilePic = avatarPath
|
||||||
|
posts.append(newPost)
|
||||||
|
return posts
|
@ -6,10 +6,10 @@
|
|||||||
<img class="ui avatar image" src="{{ url_for('static',filename='img/avatars/')}}{{range(1, 12) | random}}.png">
|
<img class="ui avatar image" src="{{ url_for('static',filename='img/avatars/')}}{{range(1, 12) | random}}.png">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header" id="author"><a href="{{post.op.replace('@','')}}">{{ post.op }}</a></div>
|
<div class="header" id="author"><a href="user/{{post.op.replace('@','')}}">{{ post.op }}</a></div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<span class="category" id="time"><i class="clock icon"></i> {{post.date}} </span>
|
<span class="category" id="time"><i class="clock icon"></i> {{post.date}} </span>
|
||||||
<span class="category"><i class="retweet icon"></i> {{twitterAt}} retwitted</span>
|
<span class="category"><i class="retweet icon"></i> {{post.username}} retwitted</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>{{post.content}}</p>
|
<p>{{post.content}}</p>
|
||||||
|
@ -6,9 +6,12 @@
|
|||||||
<img class="ui avatar image" src="{{ post.profilePic }}">
|
<img class="ui avatar image" src="{{ post.profilePic }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header" id="author"><a href="{{post.op.replace('@','')}}">{{ post.op }}</a></div>
|
<div class="header" id="author"><a href="user/{{post.op.replace('@','')}}">{{ post.op }}</a></div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<span class="category" id="time"><i class="clock icon"></i> {{post.date}} </span>
|
<span class="category" id="time"><i class="clock icon"></i> {{post.date}} </span>
|
||||||
|
{% if post.isPinned %}
|
||||||
|
<span class="category" id="time"><i class="map pin icon"></i> Pinned </span>
|
||||||
|
{%endif%}
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>{{post.content}}</p>
|
<p>{{post.content}}</p>
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<div class="ui message">
|
<div class="ui info message">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
Information
|
Information
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,12 +9,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="ui one column grid" id="card-container">
|
<div class="ui one column grid" id="card-container">
|
||||||
{% for post in posts %}
|
{% if posts %}
|
||||||
{% if post.isRT %}
|
{% for post in posts %}
|
||||||
{% include '_post.html' %}
|
{% if post.isRT %}
|
||||||
{% else %}
|
{% include '_post.html' %}
|
||||||
{% include '_post_nort.html' %}
|
{% else %}
|
||||||
{% endif %}
|
{% include '_post_nort.html' %}
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
</div>
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<div>No posts</div>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
<div class="blue ui centered card">
|
<div class="blue ui centered card">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="center aligned author">
|
<div class="center aligned author">
|
||||||
<img class="ui avatar image" src="{{ profilePic }}"> {{ twitterAt }}
|
<img class="ui avatar image" src="{{ posts[0].userProfilePic }}"> {{ twitterAt }}
|
||||||
</div>
|
</div>
|
||||||
<div style="margin: .1em" class="center aligned header"><a href="https://nitter.net/{{ twitterAt.replace('@','') }}/">{{ twitterName }}</a></div>
|
<div style="margin: .1em" class="center aligned header"><a href="https://nitter.net/{{ posts[0].op.replace('@','') }}/">{{ posts[0].twitterName }}</a></div>
|
||||||
<div class="center aligned description">
|
<div class="center aligned description">
|
||||||
<a>
|
<a>
|
||||||
<i class="users icon"></i>
|
<i class="users icon"></i>
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
alembic==1.4.2
|
alembic==1.4.2
|
||||||
|
attrs==19.3.0
|
||||||
beautifulsoup4==4.9.1
|
beautifulsoup4==4.9.1
|
||||||
bs4==0.0.1
|
bs4==0.0.1
|
||||||
certifi==2020.6.20
|
certifi==2020.6.20
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
click==7.1.2
|
click==7.1.2
|
||||||
|
defusedxml==0.6.0
|
||||||
dnspython==1.16.0
|
dnspython==1.16.0
|
||||||
email-validator==1.1.1
|
email-validator==1.1.1
|
||||||
feedparser==5.2.1
|
feedparser==5.2.1
|
||||||
@ -12,11 +14,15 @@ Flask-Login==0.5.0
|
|||||||
Flask-Migrate==2.5.3
|
Flask-Migrate==2.5.3
|
||||||
Flask-SQLAlchemy==2.4.3
|
Flask-SQLAlchemy==2.4.3
|
||||||
Flask-WTF==0.14.3
|
Flask-WTF==0.14.3
|
||||||
|
future==0.18.2
|
||||||
idna==2.10
|
idna==2.10
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
Jinja2==2.11.2
|
Jinja2==2.11.2
|
||||||
|
llvmlite==0.33.0
|
||||||
|
lxml==4.5.2
|
||||||
Mako==1.1.3
|
Mako==1.1.3
|
||||||
MarkupSafe==1.1.1
|
MarkupSafe==1.1.1
|
||||||
|
numpy==1.19.0
|
||||||
python-dateutil==2.8.1
|
python-dateutil==2.8.1
|
||||||
python-dotenv==0.14.0
|
python-dotenv==0.14.0
|
||||||
python-editor==1.0.4
|
python-editor==1.0.4
|
||||||
|
Reference in New Issue
Block a user