New version 1.2

This commit is contained in:
Wire 2020-07-13 16:36:45 +02:00
parent 26b9e465f1
commit 8891c275cf
8 changed files with 119 additions and 52 deletions

View File

@ -62,7 +62,6 @@ class twitterPost():
validPost = True
content = "El gato siguió a la liebre. Esto es un texto de ejemplo."
profilePic = "url"
twitterAt = "@error"
twitterName = "Error Name"
timeStamp = "error"

View File

@ -3,11 +3,16 @@ from flask import render_template, flash, redirect, url_for, request
from app.forms import LoginForm, RegistrationForm, EmptyForm, SearchForm
from app.models import User, twitterPost
from werkzeug.urls import url_parse
from bs4 import BeautifulSoup
from flask import Markup
from app import app, db
import time, datetime
import random, string
import feedparser
import requests
nitterInstance = "https://nitter.net/"
nitterInstanceII = "https://nitter.mastodont.cat"
@app.route('/')
@app.route('/index')
@ -17,21 +22,20 @@ def index():
followed = current_user.followed.count()
posts = []
avatarPath = "img/avatars/1.png"
form = EmptyForm()
for fwd in following:
avatarPath = "img/avatars/{}.png".format(str(random.randint(1,12)))
#Gather profile info.
rssFeed = feedparser.parse('https://nitter.net/{}/rss'.format(fwd.username))
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.profilePic = rssFeed.channel.image.url
newPost.twitterAt = rssFeed.feed.title.split("/")[1].replace(" ", "")
newPost.twitterName = rssFeed.feed.title.split("/")[0]
newPost.username = rssFeed.feed.title.split("/")[0]
newPost.date = getTimeDiff(post.published_parsed)
newPost.timeStamp = datetime.datetime(*post.published_parsed[:6])
@ -41,11 +45,16 @@ def index():
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)
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'])
@ -76,32 +85,37 @@ def logout():
def register():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = RegistrationForm()
if form.validate_on_submit():
rssFeed = feedparser.parse('https://nitter.net/{}/rss'.format(form.username.data))
if rssFeed.entries == []:
if isTwitterUser(form.username.data):
flash('This is username is taken! Choose a different one.')
else:
user = User(username=form.username.data, email=form.email.data)
user.set_password(form.password.data)
db.session.add(user)
db.session.commit()
flash('Congratulations, you are now a registered user!')
return redirect(url_for('login'))
else:
flash('This is username is taken! Choose a different one.')
return render_template('register.html', title='Register', form=form)
@app.route('/savePost/<url>', methods=['POST'])
@login_required
def savePost(url):
print("SAVEPOST")
print("Saved {}.".format(url.replace('~', '/')))
return redirect(url_for('index'))
@app.route('/follow/<username>', methods=['POST'])
@login_required
def follow(username):
form = EmptyForm()
if form.validate_on_submit():
user = User.query.filter_by(username=username).first()
isTwitter = True
isTwitter = isTwitterUser(username)
if user is None and isTwitter:
x = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(16))
newUser = User(username=username, email="{}@person.is".format(x))
print(x)
db.session.add(newUser)
db.session.commit()
flash('You are now following {}!'.format(username))
@ -168,13 +182,20 @@ def following():
@login_required
def search():
form = SearchForm()
parsedResults = []
if form.validate_on_submit():
user = form.username.data
if isTwitterUser(user):
return redirect(url_for('user', username=user))
r = requests.get("{instance}search?f=users&q={usern}".format(instance=nitterInstance, usern=user))
html = BeautifulSoup(str(r.content), features="lxml")
results = html.body.find_all('a', attrs={'class':'tweet-link'})
parsedResults = [s['href'].replace("/", "") for s in results]
return render_template('search.html', form = form, results = parsedResults)
else:
flash("User {} does not exist!".format(user))
return render_template('search.html', form = form)
return render_template('search.html', form = form, results = parsedResults)
else:
return render_template('search.html', form = form)
@ -188,32 +209,30 @@ def notfound():
@login_required
def user(username):
user = User.query.filter_by(username=username).first()
isTwitter = True
rssFeed = feedparser.parse('https://nitter.net/{}/rss'.format(username))
if rssFeed.entries == []:
isTwitter = False
if user is None and isTwitter:
isTwitter = isTwitterUser(username)
if isTwitter and user is None:
x = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(16))
newUser = User(username=username, email="{}@person.is".format(x))
db.session.add(newUser)
db.session.commit()
#flash('User {} not found.'.format(username))
elif not isTwitter and user is None:
return redirect(url_for('notfound'))
#Gather profile info.
rssFeed = feedparser.parse('https://nitter.net/{}/rss'.format(username))
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 = []
for post in rssFeed.entries:
newPost = twitterPost()
newPost.profilePic = rssFeed.channel.image.url
newPost.twitterAt = rssFeed.feed.title.split("/")[1].replace(" ", "")
newPost.twitterName = rssFeed.feed.title.split("/")[0]
newPost.username = rssFeed.feed.title.split("/")[0]
newPost.date = getTimeDiff(post.published_parsed)
newPost.timeStamp = datetime.datetime(*post.published_parsed[:6])
@ -223,35 +242,37 @@ def user(username):
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()
user = User.query.filter_by(username=username).first()
return render_template('user.html', user=user, posts=posts, form=form, profilePic=rssFeed.channel.image.url)
return render_template('user.html', user=user, posts=posts, form=form, profilePic=profilePicture, twitterAt=twitterAt, twitterName=twitterName)
def getTimeDiff(t):
today = datetime.datetime.now()
tweetTime = datetime.datetime(*t[:6])
diff = today - tweetTime
timeString = "0m"
diff = datetime.datetime.now() - tweetTime
if diff.days == 0:
minutes = diff.seconds/60
if minutes > 60:
hours = minutes/60
timeString = "{}h".format(hours)
if diff.seconds > 3599:
timeString = "{}h".format(int((diff.seconds/60)/60))
else:
timeString = "{}m".format(minutes)
timeString = "{}m".format(int(diff.seconds/60))
else:
timeString = "{}d".format(diff.days)
return timeString
def isTwitterUser(username):
rssFeed = feedparser.parse('https://nitter.net/{}/rss'.format(username))
if rssFeed.entries == []:
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:
return False
return True

BIN
app/static/img/empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -6,14 +6,23 @@
<img class="ui avatar image" src="{{ url_for('static',filename='img/avatars/')}}{{range(1, 12) | random}}.png">
</div>
</div>
<div class="header" id="author"><a href="{{ post.urlToPost }}">{{ post.op }}</a></div>
<div class="header" id="author"><a href="{{post.op.replace('@','')}}">{{ post.op }}</a></div>
<div class="meta">
<span class="category" id="time"><i class="clock icon"></i> {{post.date}} </span>
<span class="category"><i class="retweet icon"></i> {{post.twitterAt}} retwitted</span>
<span class="category"><i class="retweet icon"></i> {{twitterAt}} retwitted</span>
</div>
<div class="description">
<p>{{post.content}}</p>
</div>
<div class="extra content">
<p>
<form class="ui form" action="{{ url_for('savePost', url=post.urlToPost.replace('/', '~')) }}" method="post">
<button type="submit" class="ui icon button">
<i class="bookmark outline icon"></i>
</button>
</form>
</p>
</div>
</div>
<!--<div class="extra content">
<i class="like icon"></i> 1000

View File

@ -6,13 +6,22 @@
<img class="ui avatar image" src="{{ post.profilePic }}">
</div>
</div>
<div class="header" id="author"><a href="{{ post.urlToPost }}">{{ post.op }}</a></div>
<div class="header" id="author"><a href="{{post.op.replace('@','')}}">{{ post.op }}</a></div>
<div class="meta">
<span class="category" id="time"><i class="clock icon"></i> {{post.date}} </span>
</div>
<div class="description">
<p>{{post.content}}</p>
</div>
<div class="extra content">
<p>
<form class="ui form" action="{{ url_for('savePost', url=post.urlToPost.replace('/', '~')) }}" method="post">
<button type="submit" class="ui icon button">
<i class="bookmark outline icon"></i>
</button>
</form>
</p>
</div>
</div>
<!--<div class="extra content">
<i class="like icon"></i> 1000

View File

@ -21,6 +21,7 @@
{% else %}
<a href="{{ url_for('search') }}" class="item">Search</a>
<a href="{{ url_for('following') }}" class="item">Following</a>
<a href="{{ url_for('logout') }}" class="item">Saved</a>
<a href="{{ url_for('logout') }}" class="item">Logout</a>
{% endif %}
</div>

View File

@ -13,6 +13,21 @@
</p>
<p>{{ form.submit() }}</p>
</form>
{% if results %}
<div style="margin: 0em;" class="ui one column centered grid">
<div class="ui center aligned divided list">
{% for res in results %}
<div class="item">
<img class="ui avatar image" src="{{ url_for('static',filename='img/avatars/')}}{{range(1, 12) | random}}.png">
<div class="content">
<a href="/user/{{res}}">{{res}}</a>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -4,9 +4,9 @@
<div class="blue ui centered card">
<div class="content">
<div class="center aligned author">
<img class="ui avatar image" src="{{ profilePic }}"> {{ posts[0].twitterAt }}
<img class="ui avatar image" src="{{ profilePic }}"> {{ twitterAt }}
</div>
<div style="margin: .1em" class="center aligned header"><a href="https://nitter.net/{{ posts[0].twitterAt.replace('@','') }}/">{{ posts[0].twitterName }}</a></div>
<div style="margin: .1em" class="center aligned header"><a href="https://nitter.net/{{ twitterAt.replace('@','') }}/">{{ twitterName }}</a></div>
<div class="center aligned description">
<a>
<i class="users icon"></i>
@ -38,12 +38,25 @@
</div>
<div class="ui one column grid" id="card-container">
{% for post in posts %}
{% if post.isRT %}
{% include '_post.html' %}
{% else %}
{% include '_post_nort.html' %}
{% endif %}
{% endfor %}
{% if not posts %}
<div style="margin-top: 2em;" class="ui one column centered grid">
<div style="margin: 1.5em;" class="ui row">
<img class="ui medium circular image" src="{{ url_for('static',filename='img/empty.png') }}">
</div>
<div style="margin: 1.5em;" class="ui row">
<h2 class="ui header">This feed is empty.</h2>
</div>
</div>
{% else %}
{% for post in posts %}
{% if post.isRT %}
{% include '_post.html' %}
{% else %}
{% include '_post_nort.html' %}
{% endif %}
{% endfor %}
{% endif %}
</div>
{% endblock %}