Merge branch 'dev-indep' of https://github.com/ytorg/yotter into dev-indep
This commit is contained in:
commit
d1ec8e20b6
@ -1,5 +1,7 @@
|
|||||||
.git
|
.git
|
||||||
|
.github
|
||||||
.gitignore
|
.gitignore
|
||||||
|
cache
|
||||||
Dockerfile
|
Dockerfile
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
LICENSE
|
LICENSE
|
||||||
|
7
.github/dependabot.yml
vendored
Normal file
7
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# Maintain dependencies for GitHub Actions
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
45
.github/workflows/docker-build.yml
vendored
Normal file
45
.github/workflows/docker-build.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
name: Docker Multi-Architecture Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths-ignore:
|
||||||
|
- "**.md"
|
||||||
|
branches:
|
||||||
|
- dev-indep
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
with:
|
||||||
|
platforms: all
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: cache docker cache
|
||||||
|
uses: actions/cache@v2.1.1
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/cache
|
||||||
|
key: ${{ runner.os }}-docker-${{ hashFiles('**/requirements.txt') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-docker-${{ hashFiles('**/requirements.txt') }}
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: ytorg/yotter:latest
|
||||||
|
cache-from: type=local,src=cache
|
||||||
|
cache-to: type=local,dest=cache
|
@ -47,7 +47,6 @@ YOUTUBERSS = "https://www.youtube.com/feeds/videos.xml?channel_id="
|
|||||||
##########################
|
##########################
|
||||||
#### Global variables ####
|
#### Global variables ####
|
||||||
##########################
|
##########################
|
||||||
ALLOWED_EXTENSIONS = {'json', 'db'}
|
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
#### Twitter Logic ######
|
#### Twitter Logic ######
|
||||||
@ -296,28 +295,34 @@ def ytsearch():
|
|||||||
def ytfollow(channelId):
|
def ytfollow(channelId):
|
||||||
form = EmptyForm()
|
form = EmptyForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
r = followYoutubeChannel(channelId)
|
r = followYoutubeChannel(channelId)
|
||||||
return redirect(request.referrer)
|
return redirect(request.referrer)
|
||||||
|
|
||||||
def followYoutubeChannel(channelId):
|
def followYoutubeChannel(channelId):
|
||||||
channelData = YoutubeSearch.channelInfo(channelId, False)
|
|
||||||
try:
|
try:
|
||||||
if not current_user.is_following_yt(channelId):
|
channelData = YoutubeSearch.channelInfo(channelId, False)
|
||||||
follow = youtubeFollow()
|
try:
|
||||||
follow.channelId = channelId
|
if not current_user.is_following_yt(channelId):
|
||||||
follow.channelName = channelData[0]['name']
|
follow = youtubeFollow()
|
||||||
follow.followers.append(current_user)
|
follow.channelId = channelId
|
||||||
db.session.add(follow)
|
follow.channelName = channelData[0]['name']
|
||||||
db.session.commit()
|
follow.followers.append(current_user)
|
||||||
flash("{} followed!".format(channelData[0]['name']))
|
db.session.add(follow)
|
||||||
return True
|
db.session.commit()
|
||||||
else:
|
flash("{} followed!".format(channelData[0]['name']))
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
flash("Youtube: Couldn't follow {}. Already followed?".format(channelData[0]['name']))
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except KeyError as ke:
|
||||||
print(e)
|
print("KeyError: {}:'{}' could not be found".format(ke, channelId))
|
||||||
flash("Youtube: Couldn't follow {}. Already followed?".format(channelData[0]['name']))
|
flash("Youtube: ChannelId '{}' is not valid".format(channelId))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@app.route('/ytunfollow/<channelId>', methods=['POST'])
|
@app.route('/ytunfollow/<channelId>', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def ytunfollow(channelId):
|
def ytunfollow(channelId):
|
||||||
@ -571,16 +576,12 @@ def importdata():
|
|||||||
if file.filename == '':
|
if file.filename == '':
|
||||||
flash('No selected file')
|
flash('No selected file')
|
||||||
return redirect(request.referrer)
|
return redirect(request.referrer)
|
||||||
if file and allowed_file(file.filename) or 'subscription_manager' in file.filename:
|
else:
|
||||||
option = request.form['import_format']
|
option = request.form['import_format']
|
||||||
if option == 'yotter':
|
if option == 'yotter':
|
||||||
importYotterSubscriptions(file)
|
importYotterSubscriptions(file)
|
||||||
elif option == 'newpipe':
|
|
||||||
importNewPipeSubscriptions(file)
|
|
||||||
elif option == 'youtube':
|
elif option == 'youtube':
|
||||||
importYoutubeSubscriptions(file)
|
importYoutubeSubscriptions(file)
|
||||||
elif option == 'freetube':
|
|
||||||
importFreeTubeSubscriptions(file)
|
|
||||||
return redirect(request.referrer)
|
return redirect(request.referrer)
|
||||||
|
|
||||||
return redirect(request.referrer)
|
return redirect(request.referrer)
|
||||||
@ -594,37 +595,25 @@ def deleteme():
|
|||||||
logout_user()
|
logout_user()
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
def importYoutubeSubscriptions(file):
|
||||||
|
filename = secure_filename(file.filename)
|
||||||
|
try:
|
||||||
|
data = re.findall('(UC[a-zA-Z0-9_-]{22})|(?<=user/)[a-zA-Z0-9_-]+', file.read().decode('utf-8'))
|
||||||
|
for acc in data:
|
||||||
|
r = followYoutubeChannel(acc)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
flash("File is not valid.")
|
||||||
|
|
||||||
def importYotterSubscriptions(file):
|
def importYotterSubscriptions(file):
|
||||||
filename = secure_filename(file.filename)
|
filename = secure_filename(file.filename)
|
||||||
data = json.load(file)
|
data = json.load(file)
|
||||||
for acc in data['twitter']:
|
for acc in data['twitter']:
|
||||||
r = followTwitterAccount(acc['username'])
|
r = followTwitterAccount(acc['username'])
|
||||||
|
|
||||||
for acc in data['youtube']:
|
for acc in data['youtube']:
|
||||||
r = followYoutubeChannel(acc['channelId'])
|
r = followYoutubeChannel(acc['channelId'])
|
||||||
|
|
||||||
def importNewPipeSubscriptions(file):
|
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
data = json.load(file)
|
|
||||||
for acc in data['subscriptions']:
|
|
||||||
r = followYoutubeChannel(re.search('(UC[a-zA-Z0-9_-]{22})|(?<=user\/)[a-zA-Z0-9_-]+', acc['url']).group())
|
|
||||||
|
|
||||||
def importYoutubeSubscriptions(file):
|
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
itemlist = minidom.parse(file).getElementsByTagName('outline')
|
|
||||||
for item in itemlist[1:]:
|
|
||||||
r = followYoutubeChannel(re.search('UC[a-zA-Z0-9_-]{22}', item.attributes['xmlUrl'].value).group())
|
|
||||||
|
|
||||||
def importFreeTubeSubscriptions(file):
|
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
data = re.findall('UC[a-zA-Z0-9_-]{22}', file.read().decode('utf-8'))
|
|
||||||
for acc in data:
|
|
||||||
r = followYoutubeChannel(acc)
|
|
||||||
|
|
||||||
def allowed_file(filename):
|
|
||||||
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
|
||||||
|
|
||||||
@app.route('/register', methods=['GET', 'POST'])
|
@app.route('/register', methods=['GET', 'POST'])
|
||||||
def register():
|
def register():
|
||||||
form = RegistrationForm()
|
form = RegistrationForm()
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
<div class="ui blue segment">
|
<div class="ui blue segment">
|
||||||
<i class="large upload middle aligned icon"></i>
|
<i class="large upload middle aligned icon"></i>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="description"><h5 class="ui header">Import suscription data</h5></div>
|
<div class="description"><h5 class="ui header">Import subscription data</h5></div>
|
||||||
<form action = "{{ url_for('importdata') }}" method = "POST" enctype = "multipart/form-data">
|
<form action = "{{ url_for('importdata') }}" method = "POST" enctype = "multipart/form-data">
|
||||||
<input type = "file" name = "file"/>
|
<input type = "file" name = "file"/>
|
||||||
<input type = "submit"/>
|
<input type = "submit"/>
|
||||||
@ -39,15 +39,9 @@
|
|||||||
<label class="radio-inline">
|
<label class="radio-inline">
|
||||||
<input type="radio" name="import_format" id="yotter" value="yotter" checked> Yotter
|
<input type="radio" name="import_format" id="yotter" value="yotter" checked> Yotter
|
||||||
</label>
|
</label>
|
||||||
<label class="radio-inline">
|
<label class="radio-inline" data-tooltip="Includes FreeTube, Invidious and NewPipe.">
|
||||||
<input type="radio" name="import_format" id="newpipe" value="newpipe"> NewPipe
|
|
||||||
</label>
|
|
||||||
<label class="radio-inline">
|
|
||||||
<input type="radio" name="import_format" id="youtube" value="youtube"> Youtube
|
<input type="radio" name="import_format" id="youtube" value="youtube"> Youtube
|
||||||
</label>
|
</label>
|
||||||
<label class="radio-inline">
|
|
||||||
<input type="radio" name="import_format" id="freetube" value="freetube"> FreeTube
|
|
||||||
</label>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user