nextcloud links 90% working
This commit is contained in:
parent
2114ed037a
commit
c8df93dd5f
@ -81,7 +81,7 @@ class StorageForm(forms.ModelForm):
|
|||||||
class SyncForm(forms.ModelForm):
|
class SyncForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Sync
|
model = Sync
|
||||||
fields = ('storage', 'path')
|
fields = ('storage', 'path', 'active')
|
||||||
|
|
||||||
|
|
||||||
class BatchEditForm(forms.Form):
|
class BatchEditForm(forms.Form):
|
||||||
|
23
cookbook/migrations/0007_auto_20191114_1044.py
Normal file
23
cookbook/migrations/0007_auto_20191114_1044.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 2.2.7 on 2019-11-14 09:44
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cookbook', '0006_comment'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sync',
|
||||||
|
name='active',
|
||||||
|
field=models.BooleanField(default=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='storage',
|
||||||
|
name='method',
|
||||||
|
field=models.CharField(choices=[('DB', 'Dropbox'), ('DAV', 'WebDAV')], default='DB', max_length=128),
|
||||||
|
),
|
||||||
|
]
|
18
cookbook/migrations/0008_auto_20191114_1046.py
Normal file
18
cookbook/migrations/0008_auto_20191114_1046.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.2.7 on 2019-11-14 09:46
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cookbook', '0007_auto_20191114_1044'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='storage',
|
||||||
|
name='method',
|
||||||
|
field=models.CharField(choices=[('DB', 'Dropbox'), ('NEXTCLOUD', 'Nextcloud')], default='DB', max_length=128),
|
||||||
|
),
|
||||||
|
]
|
@ -4,8 +4,8 @@ from django.db import models
|
|||||||
|
|
||||||
class Storage(models.Model):
|
class Storage(models.Model):
|
||||||
DROPBOX = 'DB'
|
DROPBOX = 'DB'
|
||||||
DAV = 'DAV'
|
NEXTCLOUD = 'NEXTCLOUD'
|
||||||
STORAGE_TYPES = ((DROPBOX, 'Dropbox'), (DAV, 'WebDAV'))
|
STORAGE_TYPES = ((DROPBOX, 'Dropbox'), (NEXTCLOUD, 'Nextcloud'))
|
||||||
|
|
||||||
name = models.CharField(max_length=128)
|
name = models.CharField(max_length=128)
|
||||||
method = models.CharField(choices=STORAGE_TYPES, max_length=128, default=DROPBOX)
|
method = models.CharField(choices=STORAGE_TYPES, max_length=128, default=DROPBOX)
|
||||||
@ -21,6 +21,7 @@ class Storage(models.Model):
|
|||||||
class Sync(models.Model):
|
class Sync(models.Model):
|
||||||
storage = models.ForeignKey(Storage, on_delete=models.PROTECT)
|
storage = models.ForeignKey(Storage, on_delete=models.PROTECT)
|
||||||
path = models.CharField(max_length=512, default="")
|
path = models.CharField(max_length=512, default="")
|
||||||
|
active = models.BooleanField(default=True)
|
||||||
last_checked = models.DateTimeField()
|
last_checked = models.DateTimeField()
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
96
cookbook/provider/nextcloud.py
Normal file
96
cookbook/provider/nextcloud.py
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
import webdav3.client as wc
|
||||||
|
import requests
|
||||||
|
import xmltodict
|
||||||
|
|
||||||
|
from requests.auth import HTTPBasicAuth
|
||||||
|
|
||||||
|
from cookbook.models import Recipe, RecipeImport, SyncLog
|
||||||
|
from cookbook.provider.provider import Provider
|
||||||
|
|
||||||
|
|
||||||
|
class Nextcloud(Provider):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def import_all(monitor):
|
||||||
|
options = {
|
||||||
|
'webdav_hostname': monitor.storage.url + '/remote.php/dav/files/' + monitor.storage.username,
|
||||||
|
'webdav_login': monitor.storage.username,
|
||||||
|
'webdav_password': monitor.storage.password
|
||||||
|
}
|
||||||
|
client = wc.Client(options)
|
||||||
|
|
||||||
|
files = client.list(monitor.path)
|
||||||
|
files.pop(0) # remove first element because its the folder itself
|
||||||
|
|
||||||
|
import_count = 0
|
||||||
|
for file in files:
|
||||||
|
path = monitor.path + '/' + file
|
||||||
|
if not Recipe.objects.filter(file_path=path).exists() and not RecipeImport.objects.filter(file_path=path).exists():
|
||||||
|
name = os.path.splitext(file)[0]
|
||||||
|
new_recipe = RecipeImport(name=name, file_path=path, storage=monitor.storage)
|
||||||
|
new_recipe.save()
|
||||||
|
import_count += 1
|
||||||
|
|
||||||
|
log_entry = SyncLog(status='SUCCESS', msg='Imported ' + str(import_count) + ' recipes', sync=monitor)
|
||||||
|
log_entry.save()
|
||||||
|
|
||||||
|
monitor.last_checked = datetime.now()
|
||||||
|
monitor.save()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def url_from_ocs_response(response):
|
||||||
|
if response['ocs']['data']:
|
||||||
|
elements = response['ocs']['data']['element']
|
||||||
|
if isinstance(elements, list):
|
||||||
|
for element in elements:
|
||||||
|
if element['share_type'] == '3':
|
||||||
|
return element['url']
|
||||||
|
else:
|
||||||
|
if elements['share_type'] == '3':
|
||||||
|
return elements['url']
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_share_link(recipe):
|
||||||
|
url = recipe.storage.url + '/ocs/v2.php/apps/files_sharing/api/v1/shares'
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"path": recipe.file_path,
|
||||||
|
"shareType ": 3
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.post(url, headers=headers, auth=HTTPBasicAuth(recipe.storage.username, recipe.storage.password), data=json.dumps(data))
|
||||||
|
|
||||||
|
json_response = xmltodict.parse(r.text)
|
||||||
|
|
||||||
|
return Nextcloud.url_from_ocs_response(json_response)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_share_link(recipe):
|
||||||
|
url = recipe.storage.url + '/ocs/v2.php/apps/files_sharing/api/v1/shares?path=' + recipe.file_path
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
"Content-Type": "application/xml"
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.get(url, headers=headers, auth=HTTPBasicAuth(recipe.storage.username, recipe.storage.password))
|
||||||
|
|
||||||
|
json_response = xmltodict.parse(r.text)
|
||||||
|
|
||||||
|
url = Nextcloud.url_from_ocs_response(json_response)
|
||||||
|
if url:
|
||||||
|
return url
|
||||||
|
|
||||||
|
return Nextcloud.create_share_link(recipe)
|
@ -8,6 +8,7 @@ from django.shortcuts import redirect
|
|||||||
from cookbook.models import Recipe, Sync, Storage
|
from cookbook.models import Recipe, Sync, Storage
|
||||||
from cookbook.provider import dropbox
|
from cookbook.provider import dropbox
|
||||||
from cookbook.provider.dropbox import Dropbox
|
from cookbook.provider.dropbox import Dropbox
|
||||||
|
from cookbook.provider.nextcloud import Nextcloud
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@ -20,13 +21,17 @@ def get_file_link(request, recipe_id):
|
|||||||
if recipe.link == "":
|
if recipe.link == "":
|
||||||
recipe.link = Dropbox.get_share_link(recipe) # TODO response validation
|
recipe.link = Dropbox.get_share_link(recipe) # TODO response validation
|
||||||
recipe.save()
|
recipe.save()
|
||||||
|
if recipe.storage.method == Storage.NEXTCLOUD:
|
||||||
|
if recipe.link == "":
|
||||||
|
recipe.link = Nextcloud.get_share_link(recipe) # TODO response validation
|
||||||
|
#recipe.save()
|
||||||
|
|
||||||
return HttpResponse(recipe.link)
|
return HttpResponse(recipe.link)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def sync_all(request):
|
def sync_all(request):
|
||||||
monitors = Sync.objects.all()
|
monitors = Sync.objects.filter(active=True)
|
||||||
|
|
||||||
error = False
|
error = False
|
||||||
for monitor in monitors:
|
for monitor in monitors:
|
||||||
@ -34,6 +39,10 @@ def sync_all(request):
|
|||||||
ret = Dropbox.import_all(monitor)
|
ret = Dropbox.import_all(monitor)
|
||||||
if not ret:
|
if not ret:
|
||||||
error = True
|
error = True
|
||||||
|
if monitor.storage.method == Storage.NEXTCLOUD:
|
||||||
|
ret = Nextcloud.import_all(monitor)
|
||||||
|
if not ret:
|
||||||
|
error = True
|
||||||
|
|
||||||
if not error:
|
if not error:
|
||||||
messages.add_message(request, messages.SUCCESS, _('Sync successful!'))
|
messages.add_message(request, messages.SUCCESS, _('Sync successful!'))
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
six
|
lxml
|
||||||
requests
|
|
||||||
markdown
|
|
||||||
django
|
django
|
||||||
django-tables2
|
django-tables2
|
||||||
django-filter
|
django-filter
|
||||||
django-crispy-forms
|
django-crispy-forms
|
||||||
djangorestframework
|
djangorestframework
|
||||||
django-autocomplete-light
|
django-autocomplete-light
|
||||||
|
six
|
||||||
|
requests
|
||||||
|
markdown
|
||||||
|
webdavclient3
|
||||||
|
xmltodict
|
||||||
python-dotenv==0.7.1
|
python-dotenv==0.7.1
|
||||||
psycopg2==2.7.4
|
psycopg2==2.7.4
|
||||||
gunicorn==19.7.1
|
gunicorn==19.7.1
|
Loading…
Reference in New Issue
Block a user