intern mit etherpad
This commit is contained in:
@@ -1 +1,16 @@
|
||||
from .api import getPadHTML, setPadHTML, createPadifNotExists
|
||||
|
||||
from .api import getPadHTML, setPadHTML, createPadifNotExists, get_pad_link
|
||||
from .parse import to_key, to_path, parse_html_from_ep
|
||||
|
||||
|
||||
|
||||
def getInternPadHTML(key):
|
||||
key = to_key(key)
|
||||
createPadifNotExists(key, groupName="intern")
|
||||
html = getPadHTML(to_key(key), groupName="intern")
|
||||
|
||||
return parse_html_from_ep(html, key)
|
||||
|
||||
|
||||
def get_int_pad_link(path):
|
||||
return get_pad_link(to_key(path), groupName="intern")
|
||||
@@ -2,18 +2,15 @@ from django.conf import settings
|
||||
|
||||
import os
|
||||
import urllib.parse
|
||||
|
||||
from etherpad_lite import EtherpadLiteClient, EtherpadException
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from .parse import ToText
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
SERVER_URL = settings.ETHERPAD_CLIENT["exturl"]
|
||||
|
||||
|
||||
@contextmanager
|
||||
def ignore_ep_exception(msg="", *exceptions):
|
||||
try:
|
||||
@@ -21,7 +18,7 @@ def ignore_ep_exception(msg="", *exceptions):
|
||||
except exceptions as e:
|
||||
logger.error(msg)
|
||||
logger.error("%s", e)
|
||||
|
||||
|
||||
|
||||
def get_ep_client(groupName="fet"):
|
||||
epc = None
|
||||
@@ -29,8 +26,7 @@ def get_ep_client(groupName="fet"):
|
||||
|
||||
with ignore_ep_exception("Error connecting to Etherpad", Exception):
|
||||
with open(os.path.abspath(settings.ETHERPAD_CLIENT["apikey"]), "r") as f:
|
||||
apikey = f.read()
|
||||
apikey = apikey.rstrip()
|
||||
apikey = f.read().rstrip()
|
||||
epc = EtherpadLiteClient(
|
||||
base_params={
|
||||
"apikey": apikey,
|
||||
@@ -42,6 +38,7 @@ def get_ep_client(groupName="fet"):
|
||||
|
||||
return epc, group
|
||||
|
||||
|
||||
@contextmanager
|
||||
def ep_client(groupName="fet"):
|
||||
epc, group = get_ep_client(groupName)
|
||||
@@ -52,43 +49,63 @@ def ep_client(groupName="fet"):
|
||||
yield epc, group
|
||||
|
||||
|
||||
def __checkPadExists(padID=None):
|
||||
def __checkPadExists(padID=None, groupName="fet"):
|
||||
if not padID:
|
||||
return False
|
||||
|
||||
with ep_client() as (epc, group):
|
||||
with ep_client(groupName) as (epc, group):
|
||||
if not epc or not group:
|
||||
return None
|
||||
lists = epc.listPads(groupID=group["groupID"])
|
||||
lists = epc.listPads(groupID = group["groupID"])
|
||||
if str(padID) in lists["padIDs"]:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def createPadifNotExists(padID):
|
||||
if not __checkPadExists(padID=padID):
|
||||
with ep_client() as (epc, group):
|
||||
def list_pads(groupName="fet"):
|
||||
with ep_client(groupName) as (epc, group):
|
||||
return [p.split("$")[1] for p in epc.listPads(groupID = group["groupID"])["padIDs"]]
|
||||
|
||||
def list_main_pads(groupName="intern"):
|
||||
def is_main(s):
|
||||
return len(s.split("-")) == 1
|
||||
return list(filter(is_main, list_pads(groupName)))
|
||||
|
||||
def clean_up_pads(groupName="intern"):
|
||||
with ep_client(groupName) as (epc, group):
|
||||
for pid in epc.listPads(groupID = group["groupID"])["padIDs"]:
|
||||
print(pid)
|
||||
html = epc.getHTML(padID=pid)["html"]
|
||||
if ToText(html) == "":
|
||||
print(f"Deleting...${pid}")
|
||||
epc.deletePad(padID = pid)
|
||||
return
|
||||
|
||||
|
||||
def createPadifNotExists(padID, groupName="fet"):
|
||||
if not __checkPadExists(padID=padID, groupName=groupName):
|
||||
with ep_client(groupName) as (epc, group):
|
||||
if not epc or not group:
|
||||
return None
|
||||
epc.createGroupPad(
|
||||
groupID = group["groupID"], padName=padID, text="helloworld"
|
||||
groupID=group["groupID"], padName=padID, text="helloworld"
|
||||
)
|
||||
|
||||
return padID
|
||||
|
||||
|
||||
def getPadHTML(padID):
|
||||
def getPadHTML(padID, groupName="fet"):
|
||||
text = None
|
||||
with ep_client() as (epc, group):
|
||||
with ep_client(groupName) as (epc, group):
|
||||
if not epc or not group:
|
||||
return None
|
||||
text = epc.getHTML(padID = group["groupID"] + "$" + padID)["html"]
|
||||
return text
|
||||
|
||||
|
||||
def setPadHTML(padID, html):
|
||||
epc, group = get_ep_client()
|
||||
def setPadHTML(padID, html, groupName="fet"):
|
||||
epc, group = get_ep_client(groupName)
|
||||
if not epc or not group:
|
||||
return None
|
||||
|
||||
@@ -96,12 +113,13 @@ def setPadHTML(padID, html):
|
||||
return html
|
||||
|
||||
|
||||
def get_pad_link(padID):
|
||||
def get_pad_link(padID, groupName="fet"):
|
||||
if padID is None:
|
||||
return "#"
|
||||
with ep_client() as (epc, group):
|
||||
with ep_client(groupName) as (epc, group):
|
||||
if not epc or not group:
|
||||
return "#"
|
||||
return urllib.parse.urljoin(
|
||||
settings.ETHERPAD_CLIENT["exturl"], "p/" + group["groupID"] + "$" + str(padID)
|
||||
settings.ETHERPAD_CLIENT["exturl"],
|
||||
"p/" + group["groupID"] + "$" + str(padID),
|
||||
)
|
||||
|
||||
@@ -7,8 +7,8 @@ from authentications.decorators import ep_authenticated_user
|
||||
|
||||
|
||||
@ep_authenticated_user
|
||||
def __get_ep_sessionid(request):
|
||||
epc, group = get_ep_client()
|
||||
def __get_ep_sessionid(request, groupName="fet"):
|
||||
epc, group = get_ep_client(groupName)
|
||||
if not epc or not group:
|
||||
return None, None
|
||||
|
||||
@@ -30,8 +30,8 @@ def __get_ep_sessionid(request):
|
||||
return result["sessionID"], expires
|
||||
|
||||
|
||||
def add_ep_cookie(request, response):
|
||||
ep_sessid, expires = __get_ep_sessionid(request)
|
||||
def add_ep_cookie(request, response, groupName="fet"):
|
||||
ep_sessid, expires = __get_ep_sessionid(request, groupName=groupName)
|
||||
|
||||
if ep_sessid:
|
||||
response.set_cookie(
|
||||
|
||||
50
fet2020/documents/parse.py
Normal file
50
fet2020/documents/parse.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from slugify import slugify
|
||||
import re
|
||||
from bs4 import BeautifulSoup
|
||||
from django.urls import reverse
|
||||
from os.path import join
|
||||
from functools import partial
|
||||
|
||||
def clean_string(s):
|
||||
s = re.sub("[^\w\d\_/-]", "_", s).replace("/", "-")
|
||||
while s[-1]=="-":
|
||||
s=s[0:-1]
|
||||
return s
|
||||
|
||||
def to_key(s):
|
||||
return (clean_string(s).replace("/", "-"))
|
||||
|
||||
def to_path(s):
|
||||
return clean_string(s).replace("-","/")
|
||||
|
||||
|
||||
def create_a_link_for(v, path):
|
||||
v = v.group(1)
|
||||
v = clean_string(v).replace("-", "/")
|
||||
if path[0] != "/":
|
||||
path = join(path, v)
|
||||
while path[0]=="/":
|
||||
path = path[1:]
|
||||
|
||||
u = reverse("int", kwargs={"path": path})
|
||||
return "<a href=\"%s\">%s</a>" % (u, v)
|
||||
|
||||
|
||||
def ToText(html):
|
||||
s = BeautifulSoup(html, "html.parser").find("body")
|
||||
|
||||
return s.get_text().strip()
|
||||
|
||||
|
||||
def parse_html_from_ep(html, key):
|
||||
path = to_path(key)
|
||||
soup = BeautifulSoup(html, "html.parser")
|
||||
soup = soup.find("body")
|
||||
textNodes = soup.findAll(text=True)
|
||||
for node in textNodes:
|
||||
text = str(node)
|
||||
text = re.sub(r'^##(.+)$', r'<h2>\1</h2>', text, 0, re.M)
|
||||
text = re.sub(r'\[\[([\w\d\_/-]+)\]\]', partial(create_a_link_for, path=path), text)
|
||||
node.replaceWith(BeautifulSoup(text, 'html.parser'))
|
||||
return str(soup)
|
||||
|
||||
40
fet2020/documents/view_url.py
Normal file
40
fet2020/documents/view_url.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from . import getInternPadHTML, get_int_pad_link
|
||||
from authentications.decorators import authenticated_user
|
||||
from django.urls import path
|
||||
from django.shortcuts import render, reverse
|
||||
from .etherpadlib import add_ep_cookie
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import redirect
|
||||
from .parse import to_path
|
||||
from .api import list_main_pads, clean_up_pads
|
||||
|
||||
|
||||
@authenticated_user
|
||||
def clean_up_pads_views(request):
|
||||
clean_up_pads("intern")
|
||||
return redirect('int', path = "home")
|
||||
@authenticated_user
|
||||
def intern_view(request, path=""):
|
||||
if path != to_path(path):
|
||||
return redirect('int', path = to_path(path))
|
||||
context = {
|
||||
"body": getInternPadHTML(path),
|
||||
"link": get_int_pad_link(path),
|
||||
"main_pads": list_main_pads("intern"),
|
||||
"path": path}
|
||||
|
||||
response = render(request, "documents/intern.html", context)
|
||||
response = add_ep_cookie(request, response, "intern")
|
||||
|
||||
return response
|
||||
|
||||
@authenticated_user
|
||||
def intern_api_view(request, path=""):
|
||||
return HttpResponse(getInternPadHTML(path))
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("cleanup", clean_up_pads_views),
|
||||
path("api/<path:path>", intern_api_view, name="apiint"),
|
||||
path("<path:path>", intern_view, name="int")
|
||||
]
|
||||
@@ -38,6 +38,7 @@ urlpatterns = [
|
||||
path("member/", include(member_urlpatterns), name="member"),
|
||||
path("blackboard/", include("blackboard.urls"), name="blackboard"),
|
||||
path("tasks/", include("tasks.urls"), name="tasks"),
|
||||
path("int/", include("documents.view_url"), name="int"),
|
||||
path(
|
||||
"sitemap.xml",
|
||||
sitemap,
|
||||
|
||||
@@ -14,3 +14,4 @@ etherpad-lite==0.5
|
||||
ghostscript==0.6
|
||||
ldap3==2.8.1
|
||||
mysqlclient==2.0.1
|
||||
python-slugify
|
||||
@@ -25,3 +25,11 @@ a.thumbnail img {
|
||||
height: 150px;
|
||||
|
||||
}
|
||||
div.document {
|
||||
background: white;
|
||||
}
|
||||
div.document ul.indent li {
|
||||
list-style-type: none;
|
||||
}
|
||||
iframe.int {
|
||||
height: 95%; width: 100%; min-height: 500px; display: block}
|
||||
35
fet2020/templates/documents/intern.html
Normal file
35
fet2020/templates/documents/intern.html
Normal file
@@ -0,0 +1,35 @@
|
||||
{% extends 'layout.html' %}
|
||||
{% block extraheader %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setInterval(function(){
|
||||
jQuery.ajax({
|
||||
url: "{% url 'apiint' path %}",
|
||||
success: function (res, status) {
|
||||
jQuery("div.document")[0].innerHTML=res;
|
||||
}}
|
||||
);
|
||||
},4000)
|
||||
}, false);
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="grid-container">
|
||||
<div class="grid-x">
|
||||
<div class="medium-8 cell">
|
||||
<a href="{{link}}">Edit</a>
|
||||
{% for p in main_pads %}
|
||||
<a href="{% url 'int' p %}" class="button" >{{p}}</a>
|
||||
{% endfor %}
|
||||
<div class="document padding-1">
|
||||
{{body | safe}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-4 cell">
|
||||
<iframe class="int" src="{{link}}?"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,12 +1,13 @@
|
||||
# pylint: skip-file
|
||||
import pytest
|
||||
from posts.models import News, Post, Event, FetMeeting
|
||||
from django.urls import reverse
|
||||
from django.core.validators import ValidationError
|
||||
import datetime
|
||||
from urllib.request import URLError
|
||||
import random
|
||||
import string
|
||||
from posts.models import News, Post, Event, FetMeeting
|
||||
|
||||
|
||||
def get_random_string(size):
|
||||
chars = string.ascii_lowercase+string.ascii_uppercase+string.digits
|
||||
|
||||
Reference in New Issue
Block a user