kopia lustrzana https://github.com/wagtail/wagtail
Merge branch 'master' of github.com:torchbox/wagtail
commit
069ff69335
19
README.rst
19
README.rst
|
@ -1,8 +1,21 @@
|
|||
Wagtail CMS
|
||||
===========
|
||||
|
||||
Wagtail is a Django content management system focused on flexibility and user experience. Find out more at `wagtail.io <http://wagtail.io/>`_
|
||||
and `torchbox.github.io/wagtail <http://torchbox.github.io/wagtail/>`_.
|
||||
Wagtail is a Django content management system built originally for the `Royal College of Art <http://www.rca.ac.uk/>`_ and focused on flexibility and user experience. Its features include:
|
||||
|
||||
* A fast, attractive editor interface
|
||||
* Complete control over design with standard Django templates
|
||||
* Configure content types through standard Django models
|
||||
* Tightly integrated search (with an `Elasticsearch <http://www.elasticsearch.org/>`_ backend for production)
|
||||
* Strong document and image management
|
||||
* Wide support for embedded content
|
||||
* Simple, configurable permissions
|
||||
* Support for tree-based content organisation
|
||||
* Optional preview->submit->approve workflow
|
||||
* Fast out of the box. `Varnish <https://www.varnish-cache.org/>`_-friendly if you need it
|
||||
* Tests! But not enough; we're working hard to improve this
|
||||
|
||||
Find out more at `wagtail.io <http://wagtail.io/>`_.
|
||||
|
||||
Getting started
|
||||
~~~~~~~~~~~~~~~
|
||||
|
@ -10,4 +23,4 @@ To get you up and running quickly, we've provided a demonstration site with all
|
|||
|
||||
Contributing
|
||||
~~~~~~~~~~~~
|
||||
If you're a Python or Django developer, fork the repo and get stuck in! Send us a useful pull request and we'll post you a `t-shirt <https://twitter.com/WagtailCMS/status/432166799464210432/photo/1>`_.
|
||||
If you're a Python or Django developer, fork the repo and get stuck in! Send us a useful pull request and we'll post you a `t-shirt <https://twitter.com/WagtailCMS/status/432166799464210432/photo/1>`_. Our immediate priorities are better docs, more tests, internationalisation and localisation.
|
||||
|
|
1
setup.py
1
setup.py
|
@ -43,7 +43,6 @@ setup(
|
|||
"South>=0.8.4",
|
||||
"django-compressor>=1.3",
|
||||
"django-modelcluster>=0.1",
|
||||
"Embedly>=0.5.0",
|
||||
"django-taggit>=0.11.2",
|
||||
"Pillow>=2.3.0",
|
||||
"beautifulsoup4>=4.3.2",
|
||||
|
|
|
@ -52,7 +52,10 @@ class ImageEmbedHandler(object):
|
|||
format = get_image_format(attrs['format'])
|
||||
|
||||
if for_editor:
|
||||
return format.image_to_editor_html(image, attrs['alt'])
|
||||
try:
|
||||
return format.image_to_editor_html(image, attrs['alt'])
|
||||
except:
|
||||
return ''
|
||||
else:
|
||||
return format.image_to_html(image, attrs['alt'])
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
from .models import Embed
|
||||
from .embeds import get_embed
|
||||
from .embeds.embed import get_embed
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
from datetime import datetime
|
||||
from embedly import Embedly
|
||||
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from .models import Embed
|
||||
|
||||
import os
|
||||
module_dir = os.path.dirname(__file__) # get current directory
|
||||
file_path = os.path.join(module_dir, 'endpoints.json')
|
||||
print file_path
|
||||
print open(file_path).read()
|
||||
|
||||
def get_embed(url, max_width=None):
|
||||
|
||||
def get_embed_embedly(url, max_width=None):
|
||||
# Check database
|
||||
try:
|
||||
return Embed.objects.get(url=url, max_width=max_width)
|
||||
|
@ -52,3 +58,18 @@ def get_embed(url, max_width=None):
|
|||
|
||||
# Return new embed
|
||||
return row
|
||||
|
||||
def get_embed_oembed(url, max_width=None):
|
||||
pass
|
||||
|
||||
get_embed = get_embed_oembed
|
||||
try:
|
||||
from embedly import Embedly
|
||||
if hasattr(settings,'EMBEDLY_KEY'):
|
||||
get_embed = get_embed_embedly
|
||||
except:
|
||||
pass
|
||||
|
||||
print get_embed
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
from datetime import datetime
|
||||
from django.conf import settings
|
||||
from ..models import Embed
|
||||
import oembed_api
|
||||
|
||||
class EmbedlyException(Exception): pass
|
||||
class AccessDeniedEmbedlyException(Exception): pass
|
||||
class NotFoundEmbedlyException(Exception): pass
|
||||
|
||||
def get_embed_embedly(url, max_width=None):
|
||||
# Check database
|
||||
try:
|
||||
return Embed.objects.get(url=url, max_width=max_width)
|
||||
except Embed.DoesNotExist:
|
||||
pass
|
||||
|
||||
client = Embedly(key=settings.EMBEDLY_KEY)
|
||||
|
||||
if max_width is not None:
|
||||
oembed = client.oembed(url, maxwidth=max_width, better=False)
|
||||
else:
|
||||
oembed = client.oembed(url, better=False)
|
||||
|
||||
# Check for error
|
||||
if oembed.get('error'):
|
||||
if oembed['error_code'] in [401,403]:
|
||||
raise AccessDeniedEmbedlyException
|
||||
elif oembed['error_code'] == 404:
|
||||
raise NotFoundEmbedlyException
|
||||
else:
|
||||
raise EmbedlyException
|
||||
|
||||
return save_embed(url, max_width, oembed)
|
||||
|
||||
|
||||
def get_embed_oembed(url, max_width=None):
|
||||
# Check database
|
||||
try:
|
||||
return Embed.objects.get(url=url, max_width=max_width)
|
||||
except Embed.DoesNotExist:
|
||||
pass
|
||||
|
||||
oembed = oembed_api.get_embed_oembed(url, max_width)
|
||||
return save_embed(url, max_width, oembed)
|
||||
|
||||
|
||||
def save_embed(url, max_width, oembed):
|
||||
row, created = Embed.objects.get_or_create(
|
||||
url=url,
|
||||
max_width=max_width,
|
||||
defaults={
|
||||
'type': oembed['type'],
|
||||
'title': oembed['title'],
|
||||
'thumbnail_url': oembed.get('thumbnail_url'),
|
||||
'width': oembed.get('width'),
|
||||
'height': oembed.get('height')
|
||||
}
|
||||
)
|
||||
|
||||
if oembed['type'] == 'photo':
|
||||
html = '<img src="%s" />' % (oembed['url'], )
|
||||
else:
|
||||
html = oembed.get('html')
|
||||
|
||||
if html:
|
||||
row.html = html
|
||||
row.last_updated = datetime.now()
|
||||
row.save()
|
||||
|
||||
return row
|
||||
|
||||
# As a default use oembed
|
||||
get_embed = get_embed_oembed
|
||||
try:
|
||||
from embedly import Embedly
|
||||
# if EMBEDLY_KEY is set and embedly library found the use embedly
|
||||
if hasattr(settings,'EMBEDLY_KEY'):
|
||||
get_embed = get_embed_embedly
|
||||
except:
|
||||
pass
|
|
@ -0,0 +1,295 @@
|
|||
{
|
||||
"https://speakerdeck.com/oembed.{format}": [
|
||||
"^http(?:s)?://speakerdeck\\.com/.+$"
|
||||
],
|
||||
"https://alpha-api.app.net/oembed": [
|
||||
"^http(?:s)?://alpha\\.app\\.net/[^#?/]+/post/.+$",
|
||||
"^http(?:s)?://photos\\.app\\.net/[^#?/]+/.+$"
|
||||
],
|
||||
"http://www.youtube.com/oembed": [
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?youtube\\.com/watch.+$",
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?youtube\\.com/v/.+$",
|
||||
"^http(?:s)?://youtu\\.be/.+$",
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?youtube\\.com/user/.+$",
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?youtube\\.com/[^#?/]+#[^#?/]+/.+$",
|
||||
"^http(?:s)?://m\\.youtube\\.com/index.+$",
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?youtube\\.com/profile.+$",
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?youtube\\.com/view_play_list.+$",
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?youtube\\.com/playlist.+$"
|
||||
],
|
||||
"http://backend.deviantart.com/oembed": [
|
||||
"^http://(?:[-\\w]+\\.)?deviantart\\.com/art/.+$",
|
||||
"^http://fav\\.me/.+$",
|
||||
"^http://sta\\.sh/.+$",
|
||||
"^http://(?:[-\\w]+\\.)?deviantart\\.com/[^#?/]+#/d.+$"
|
||||
],
|
||||
"http://blip.tv/oembed/": [
|
||||
"^http://[-\\w]+\\.blip\\.tv/.+$"
|
||||
],
|
||||
"http://www.dailymotion.com/api/oembed/": [
|
||||
"^http://[-\\w]+\\.dailymotion\\.com/.+$"
|
||||
],
|
||||
"http://www.flickr.com/services/oembed/": [
|
||||
"^http://[-\\w]+\\.flickr\\.com/photos/.+$",
|
||||
"^http://flic\\.kr\\.com/.+$"
|
||||
],
|
||||
"http://www.hulu.com/api/oembed.{format}": [
|
||||
"^http://www\\.hulu\\.com/watch/.+$"
|
||||
],
|
||||
"http://www.nfb.ca/remote/services/oembed/": [
|
||||
"^http://(?:[-\\w]+\\.)?nfb\\.ca/film/.+$"
|
||||
],
|
||||
"http://qik.com/api/oembed.{format}": [
|
||||
"^http://qik\\.com/.+$",
|
||||
"^http://qik\\.ly/.+$"
|
||||
],
|
||||
"http://revision3.com/api/oembed/": [
|
||||
"^http://[-\\w]+\\.revision3\\.com/.+$"
|
||||
],
|
||||
"http://www.scribd.com/services/oembed": [
|
||||
"^http://[-\\w]+\\.scribd\\.com/.+$"
|
||||
],
|
||||
"http://www.viddler.com/oembed/": [
|
||||
"^http://[-\\w]+\\.viddler\\.com/v/.+$",
|
||||
"^http://[-\\w]+\\.viddler\\.com/explore/.+$"
|
||||
],
|
||||
"http://www.vimeo.com/api/oembed.{format}": [
|
||||
"^http(?:s)?://(?:www\\.)?vimeo\\.com/.+$",
|
||||
"^http(?:s)?://player\\.vimeo\\.com/.+$"
|
||||
],
|
||||
"http://dotsub.com/services/oembed": [
|
||||
"^http://dotsub\\.com/view/.+$"
|
||||
],
|
||||
"http://www.yfrog.com/api/oembed": [
|
||||
"^http(?:s)?://(?:www\\.)?yfrog\\.com/.+$",
|
||||
"^http(?:s)?://(?:www\\.)?yfrog\\.us/.+$"
|
||||
],
|
||||
"http://clikthrough.com/services/oembed": [
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?clikthrough\\.com/.+$"
|
||||
],
|
||||
"http://www.kinomap.com/oembed": [
|
||||
"^http://[-\\w]+\\.kinomap\\.com/.+$"
|
||||
],
|
||||
"https://photobucket.com/oembed": [
|
||||
"^http://(?:[-\\w]+\\.)?photobucket\\.com/albums/.+$",
|
||||
"^http://(?:[-\\w]+\\.)?photobucket\\.com/groups/.+$"
|
||||
],
|
||||
"http://api.instagram.com/oembed": [
|
||||
"^http://instagr\\.am/p/.+$",
|
||||
"^http://instagram\\.com/p/.+$"
|
||||
],
|
||||
"https://www.slideshare.net/api/oembed/2": [
|
||||
"^http://www\\.slideshare\\.net/.+$"
|
||||
],
|
||||
"http://tv.majorleaguegaming.com/oembed": [
|
||||
"^http://mlg\\.tv/.+$",
|
||||
"^http://tv\\.majorleaguegaming\\.com/.+$"
|
||||
],
|
||||
"http://my.opera.com/service/oembed": [
|
||||
"^http://my\\.opera\\.com/.+$"
|
||||
],
|
||||
"http://skitch.com/oembed": [
|
||||
"^http(?:s)?://(?:www\\.)?skitch\\.com/.+$",
|
||||
"^http://skit\\.ch/.+$"
|
||||
],
|
||||
"https://api.twitter.com/1/statuses/oembed.{format}": [
|
||||
"^http(?:s)?://twitter\\.com/(?:#!)?[^#?/]+/status/.+$"
|
||||
],
|
||||
"https://soundcloud.com/oembed": [
|
||||
"^https://soundcloud\\.com/[^#?/]+/.+$"
|
||||
],
|
||||
"http://www.collegehumor.com/oembed.{format}": [
|
||||
"^http://(?:www\\.)?collegehumor\\.com/video/.+$",
|
||||
"^http://(?:www\\.)?collegehumor\\.com/video:.+$"
|
||||
],
|
||||
"http://www.polleverywhere.com/services/oembed/": [
|
||||
"^http://www\\.polleverywhere\\.com/polls/.+$",
|
||||
"^http://www\\.polleverywhere\\.com/multiple_choice_polls/.+$",
|
||||
"^http://www\\.polleverywhere\\.com/free_text_polls/.+$"
|
||||
],
|
||||
"http://www.ifixit.com/Embed": [
|
||||
"^http://www\\.ifixit\\.com/[^#?/]+/[^#?/]+/.+$"
|
||||
],
|
||||
"http://api.smugmug.com/services/oembed/": [
|
||||
"^http(?:s)?://(?:www\\.)?smugmug\\.com/[^#?/]+/.+$"
|
||||
],
|
||||
"https://github.com/api/oembed": [
|
||||
"^http(?:s)?://gist\\.github\\.com/.+$"
|
||||
],
|
||||
"http://animoto.com/services/oembed": [
|
||||
"^http://animoto\\.com/play/.+$"
|
||||
],
|
||||
"http://www.rdio.com/api/oembed": [
|
||||
"^http://(?:wwww\\.)?rdio\\.com/people/[^#?/]+/playlists/.+$",
|
||||
"^http://[-\\w]+\\.rdio\\.com/artist/[^#?/]+/album/.+$"
|
||||
],
|
||||
"http://api.5min.com/oembed.{format}": [
|
||||
"^http://www\\.5min\\.com/video/.+$"
|
||||
],
|
||||
"http://500px.com/photo/{1}/oembed.{format}": [
|
||||
"^http://500px\\.com/photo/([^#?/]+)(?:.+)?$"
|
||||
],
|
||||
"http://api.dipdive.com/oembed.{format}": [
|
||||
"^http://[-\\w]+\\.dipdive\\.com/media/.+$"
|
||||
],
|
||||
"http://video.yandex.ru/oembed.{format}": [
|
||||
"^http://video\\.yandex\\.ru/users/[^#?/]+/view/.+$"
|
||||
],
|
||||
"http://www.mixcloud.com/oembed/": [
|
||||
"^http://www\\.mixcloud\\.com/oembed/[^#?/]+/.+$"
|
||||
],
|
||||
"http://www.kickstarter.com/services/oembed": [
|
||||
"^http(?:s)://[-\\w]+\\.kickstarter\\.com/projects/.+$"
|
||||
],
|
||||
"http://coub.com/api/oembed.{format}": [
|
||||
"^http(?:s)?://coub\\.com/view/.+$",
|
||||
"^http(?:s)?://coub\\.com/embed/.+$"
|
||||
],
|
||||
"http://www.screenr.com/api/oembed.{format}": [
|
||||
"^http://www\\.screenr\\.com/.+$"
|
||||
],
|
||||
"http://www.funnyordie.com/oembed.{format}": [
|
||||
"^http://www\\.funnyordie\\.com/videos/.+$"
|
||||
],
|
||||
"http://fast.wistia.com/oembed.{format}": [
|
||||
"^http://[-\\w]+\\.wista\\.com/medias/.+$"
|
||||
],
|
||||
"http://www.ustream.tv/oembed": [
|
||||
"^http(?:s)?://(?:www\\.)?ustream\\.tv/.+$",
|
||||
"^http(?:s)?://(?:www\\.)?ustream\\.com/.+$",
|
||||
"^http://ustre\\.am/.+$"
|
||||
],
|
||||
"http://wordpress.tv/oembed/": [
|
||||
"^http://wordpress\\.tv/.+$"
|
||||
],
|
||||
"http://polldaddy.com/oembed/": [
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?polldaddy\\.com/.+$"
|
||||
],
|
||||
"http://api.bambuser.com/oembed.{format}": [
|
||||
"^http://bambuser\\.com/channel/[^#?/]+/broadcast/.+$",
|
||||
"^http://bambuser\\.com/channel/.+$",
|
||||
"^http://bambuser\\.com/v/.+$"
|
||||
],
|
||||
"http://www.ted.com/talks/oembed.{format}": [
|
||||
"^http(?:s)?://(?:www\\.)?ted\\.com/talks/.+$",
|
||||
"^http(?:s)?://(?:www\\.)?ted\\.com/talks/lang/[^#?/]+/.+$",
|
||||
"^http(?:s)?://(?:www\\.)?ted\\.com/index\\.php/talks/.+$",
|
||||
"^http(?:s)?://(?:www\\.)?ted\\.com/index\\.php/talks/lang/[^#?/]+/.+$"
|
||||
],
|
||||
"http://chirb.it/oembed.{format}": [
|
||||
"^http://chirb\\.it/.+$"
|
||||
],
|
||||
"https://www.circuitlab.com/circuit/oembed/": [
|
||||
"^http(?:s)?://(?:www\\.)?circuitlab\\.com/circuit/.+$"
|
||||
],
|
||||
"http://api.geograph.org.uk/api/oembed": [
|
||||
"^http://(?:[-\\w]+\\.)?geograph\\.org\\.uk/.+$",
|
||||
"^http://(?:[-\\w]+\\.)?geograph\\.co\\.uk/.+$",
|
||||
"^http://(?:[-\\w]+\\.)?geograph\\.ie/.+$"
|
||||
],
|
||||
"http://geo.hlipp.de/restapi.php/api/oembed": [
|
||||
"^http://geo-en\\.hlipp\\.de/.+$",
|
||||
"^http://geo\\.hlipp\\.de/.+$",
|
||||
"^http://germany\\.geograph\\.org/.+$"
|
||||
],
|
||||
"http://www.geograph.org.gg/api/oembed": [
|
||||
"^http://(?:[-\\w]+\\.)?geograph\\.org\\.gg/.+$",
|
||||
"^http://(?:[-\\w]+\\.)?geograph\\.org\\.je/.+$",
|
||||
"^http://channel-islands\\.geograph\\.org/.+$",
|
||||
"^http://channel-islands\\.geographs\\.org/.+$",
|
||||
"^http://(?:[-\\w]+\\.)?channel\\.geographs\\.org/.+$"
|
||||
],
|
||||
"http://vzaar.com/api/videos/{1}.{format}": [
|
||||
"^http://(?:www\\.)?vzaar\\.com/videos/([^#?/]+)(?:.+)?$",
|
||||
"^http://www\\.vzaar\\.tv/([^#?/]+)(?:.+)?$",
|
||||
"^http://vzaar\\.tv/([^#?/]+)(?:.+)?$",
|
||||
"^http://vzaar\\.me/([^#?/]+)(?:.+)?$",
|
||||
"^http://[-\\w]+\\.vzaar\\.me/([^#?/]+)(?:.+)?$"
|
||||
],
|
||||
"http://api.minoto-video.com/services/oembed.{format}": [
|
||||
"^http://api\\.minoto-video\\.com/publishers/[^#?/]+/videos/.+$",
|
||||
"^http://dashboard\\.minoto-video\\.com/main/video/details/.+$",
|
||||
"^http://embed\\.minoto-video\\.com/.+$"
|
||||
],
|
||||
"http://www.videojug.com/oembed.{format}": [
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?videojug\\.com/film/.+$",
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?videojug\\.com/payer/.+$",
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?videojug\\.com/interview/.+$"
|
||||
],
|
||||
"http://videos.sapo.pt/oembed": [
|
||||
"^http(?:s)?://videos\\.sapo\\.pt/.+$"
|
||||
],
|
||||
"http://vhx.tv/services/oembed.{format}": [
|
||||
"^http(?:s)?://(?:www\\.)?vhx\\.tv/.+$"
|
||||
],
|
||||
"http://api.justin.tv/api/embed/from_url.{format}": [
|
||||
"^http(?:s)?://(?:www\\.)?justin\\.tv/.+$"
|
||||
],
|
||||
"http://official.fm/services/oembed.{format}": [
|
||||
"^http(?:s)?://official\\.fm/.+$"
|
||||
],
|
||||
"http://huffduffer.com/oembed": [
|
||||
"^http(?:s)?://(?:www\\.)?huffduffer\\.com/[^#?/]+/.+$"
|
||||
],
|
||||
"https://embed.spotify.com/oembed/": [
|
||||
"^http(?:s)?://open\\.spotify\\.com/.+$",
|
||||
"^http(?:s)?://spoti\\.fi/.+$"
|
||||
],
|
||||
"http://shoudio.com/api/oembed": [
|
||||
"^http://shoudio\\.com/.+$",
|
||||
"^http://shoud\\.io/.+$"
|
||||
],
|
||||
"http://api.mobypicture.com/oEmbed": [
|
||||
"^http(?:s)?://(?:www\\.)?mobypicture\\.com/user/[^#?/]+/view/.+$",
|
||||
"^http(?:s)?://(?:www\\.)?moby\\.to/.+$"
|
||||
],
|
||||
"http://www.23hq.com/23/oembed": [
|
||||
"^http(?:s)?://(?:www\\.)?23hq\\.com/[^#?/]+/photo/.+$"
|
||||
],
|
||||
"http://gmep.org/oembed.{format}": [
|
||||
"^http(?:s)?://(?:www\\.)?gmep\\.org/.+$",
|
||||
"^http(?:s)?://gmep\\.imeducate\\.com/.+$"
|
||||
],
|
||||
"http://oembed.urtak.com/1/oembed": [
|
||||
"^http(?:s)?://(?:[-\\w]+\\.)?urtak\\.com/.+$"
|
||||
],
|
||||
"http://cacoo.com/oembed.{format}": [
|
||||
"^http(?:s)?://cacoo\\.com/.+$"
|
||||
],
|
||||
"http://api.dailymile.com/oembed": [
|
||||
"^http(?:s)?://(?:www\\.)?dailymile\\.com/people/[^#?/]+/entries/.+$"
|
||||
],
|
||||
"http://www.dipity.com/oembed/timeline/": [
|
||||
"^http(?:s)?://(?:www\\.)?dipity\\.com/timeline/.+$",
|
||||
"^http(?:s)?://(?:www\\.)?dipity\\.com/voaweb/.+$"
|
||||
],
|
||||
"https://sketchfab.com/oembed": [
|
||||
"^http(?:s)?://sketchfab\\.com/show/.+$"
|
||||
],
|
||||
"https://api.meetup.com/oembed": [
|
||||
"^http(?:s)?://(?:www\\.)?meetup\\.com/.+$",
|
||||
"^http(?:s)?://(?:www\\.)?meetup\\.ps/.+$"
|
||||
],
|
||||
"https://roomshare.jp/oembed.{format}": [
|
||||
"^http(?:s)?://(?:www\\.)?roomshare\\.jp/(?:en/)?post/.+$"
|
||||
],
|
||||
"http://crowdranking.com/api/oembed.{format}": [
|
||||
"^http(?:s)?://crowdranking\\.com/crowdrankings/.+$",
|
||||
"^http(?:s)?://crowdranking\\.com/rankings/.+$",
|
||||
"^http(?:s)?://crowdranking\\.com/topics/.+$",
|
||||
"^http(?:s)?://crowdranking\\.com/widgets/.+$",
|
||||
"^http(?:s)?://crowdranking\\.com/r/.+$"
|
||||
],
|
||||
"http://openapi.etsy.com/svc/oembed/": [
|
||||
"^http(?:s)?://(?:www\\.)?etsy\\.com/listing/.+$"
|
||||
],
|
||||
"https://audioboo.fm/publishing/oembed.{format}": [
|
||||
"^http(?:s)?://audioboo\\.fm/boos/.+$"
|
||||
],
|
||||
"http://demo.clikthrough.com/services/oembed/": [
|
||||
"^http(?:s)?://demo\\.clikthrough\\.com/theater/video/.+$"
|
||||
],
|
||||
"http://www.ifttt.com/oembed/": [
|
||||
"^http(?:s)?://ifttt\\.com/recipes/.+$"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import os, re
|
||||
import urllib2, urllib
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
class NotImplementedOembedException(Exception):
|
||||
pass
|
||||
|
||||
ENDPOINTS = {}
|
||||
|
||||
def get_embed_oembed(url, max_width=None):
|
||||
provider = None
|
||||
for endpoint in ENDPOINTS.keys():
|
||||
for pattern in ENDPOINTS[endpoint]:
|
||||
if re.match(pattern, url):
|
||||
provider = endpoint
|
||||
break
|
||||
if not provider:
|
||||
raise NotImplementedOembedException
|
||||
params = {'url': url, 'format': 'json', }
|
||||
if max_width:
|
||||
params['maxwidth'] = max_width
|
||||
req = provider+'?' +urllib.urlencode(params)
|
||||
request = urllib2.Request(req)
|
||||
opener = urllib2.build_opener()
|
||||
# Some provicers were not working without a user agent
|
||||
request.add_header('User-Agent','Mozilla/5.0')
|
||||
return json.loads(opener.open(request).read())
|
||||
|
||||
|
||||
# Uses the public domain collection of oembed endpoints by Mathias Panzenbpeck (panzi)
|
||||
# at https://github.com/panzi/oembedendpoints/blob/master/endpoints-regexp.json
|
||||
|
||||
def load_oembed_endpoints():
|
||||
module_dir = os.path.dirname(__file__)
|
||||
endpoints_path = os.path.join(module_dir, 'endpoints.json')
|
||||
with open( endpoints_path) as f:
|
||||
endpoints = json.loads(f.read())
|
||||
|
||||
for endpoint in endpoints.keys():
|
||||
endpoint_key = endpoint.replace('{format}', 'json')
|
||||
|
||||
ENDPOINTS[endpoint_key]=[]
|
||||
for pattern in endpoints[endpoint]:
|
||||
ENDPOINTS[endpoint_key].append(re.compile(pattern))
|
||||
|
||||
|
||||
|
||||
load_oembed_endpoints()
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import unittest
|
||||
import oembed
|
||||
|
||||
# Test that a bunch of oembed examples is working
|
||||
# If any of these is removed or changed then the unit test will fail
|
||||
# This is a unittest TestCase (and not a django.test one) since django
|
||||
# database is not actually needed for these tests
|
||||
|
||||
TEST_DATA = [
|
||||
{
|
||||
'url':'http://www.youtube.com/watch?v=S3xAeTmsJfg',
|
||||
'title':'Animation: Ferret dance (A series of tubes)'
|
||||
},
|
||||
{
|
||||
'url':'http://vimeo.com/86036070',
|
||||
'title':'Wagtail: A new Django CMS'
|
||||
},
|
||||
{
|
||||
'url':'https://speakerdeck.com/harmstyler/an-introduction-to-django',
|
||||
'title':'An Introduction to Django'
|
||||
},
|
||||
{
|
||||
'url':'https://ifttt.com/recipes/144705-new-twitter-followers-in-a-google-spreadsheet',
|
||||
'title':'New Twitter followers in a Google spreadsheet'
|
||||
},
|
||||
{
|
||||
'url':'http://www.hulu.com/watch/20807/late-night-with-conan-obrien-wed-may-21-2008',
|
||||
'title':'Wed, May 21, 2008 (Late Night With Conan O\'Brien)'
|
||||
},
|
||||
{
|
||||
'url':'http://www.flickr.com/photos/dfluke/5995957175/',
|
||||
'title':'Django pony!?'
|
||||
},
|
||||
{
|
||||
'url':'http://www.slideshare.net/simon/the-django-web-application-framework',
|
||||
'title':'The Django Web Application Framework'
|
||||
},
|
||||
{
|
||||
'url':'http://www.rdio.com/artist/The_Black_Keys/album/Brothers/',
|
||||
'title':'Brothers'
|
||||
},
|
||||
{
|
||||
'url':'http://instagram.com/p/kFKCcEKmBq/',
|
||||
'title':'Family holidays in #Greece!'
|
||||
},
|
||||
{
|
||||
'url':'https://www.kickstarter.com/projects/noujaimfilms/the-square-a-film-about-the-egyptian-revolution',
|
||||
'title':'Sundance Award Winning Film on the Egyptian Revolution'
|
||||
},
|
||||
{
|
||||
'url':'http://www.dailymotion.com/video/xoxulz_babysitter_animals',
|
||||
'title':'Babysitter!'
|
||||
}
|
||||
]
|
||||
|
||||
class TestEmbeds(unittest.TestCase):
|
||||
def test_get_embed_oembed(self):
|
||||
for td in TEST_DATA:
|
||||
embed = oembed.get_embed_oembed_low(td['url'])
|
||||
self.assertEqual(embed['title'], td['title'] )
|
||||
self.assertIsNotNone(embed['type'] )
|
||||
self.assertIsNotNone(embed['width'] )
|
||||
self.assertIsNotNone(embed['height'] )
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -0,0 +1,114 @@
|
|||
[
|
||||
{
|
||||
"url": "http://*.blip.tv/*",
|
||||
"url_re": "blip\\.tv/.+",
|
||||
"example_url": "http://pycon.blip.tv/file/2058801/",
|
||||
"endpoint_url": "http://blip.tv/oembed/",
|
||||
"title": "blip.tv"
|
||||
},
|
||||
{
|
||||
"url": "http://*.dailymotion.com/*",
|
||||
"url_re": "dailymotion\\.com/.+",
|
||||
"example_url": "http://www.dailymotion.com/video/x5ioet_phoenix-mars-lander_tech",
|
||||
"endpoint_url": "http://www.dailymotion.com/api/oembed/",
|
||||
"title": "Dailymotion"
|
||||
},
|
||||
{
|
||||
"url": "http://*.flickr.com/photos/*",
|
||||
"url_re": "flickr\\.com/photos/[-.\\w@]+/\\d+/?",
|
||||
"example_url": "http://www.flickr.com/photos/fuffer2005/2435339994/",
|
||||
"endpoint_url": "http://www.flickr.com/services/oembed/",
|
||||
"title": "Flickr Photos"
|
||||
},
|
||||
{
|
||||
"url": "http://www.hulu.com/watch/*",
|
||||
"url_re": "hulu\\.com/watch/.*",
|
||||
"example_url": "http://www.hulu.com/watch/20807/late-night-with-conan",
|
||||
"endpoint_url": "http://www.hulu.com/api/oembed.json",
|
||||
"title": "Hulu"
|
||||
},
|
||||
{
|
||||
"url": "http://*.nfb.ca/film/*",
|
||||
"url_re": "nfb\\.ca/film/[-\\w]+/?",
|
||||
"example_url": "http://www.nfb.ca/film/blackfly/",
|
||||
"endpoint_url": "http://www.nfb.ca/remote/services/oembed/",
|
||||
"title": "National Film Board of Canada"
|
||||
},
|
||||
{
|
||||
"url": "http://qik.com/*",
|
||||
"url_re": "qik\\.com/\\w+",
|
||||
"example_url": "http://qik.com/video/86776",
|
||||
"endpoint_url": "http://qik.com/api/oembed.json",
|
||||
"title": "Qik Video"
|
||||
},
|
||||
{
|
||||
"url": "http://*.revision3.com/*",
|
||||
"url_re": "revision3\\.com/.+",
|
||||
"example_url": "http://revision3.com/diggnation/2008-04-17xsanned/",
|
||||
"endpoint_url": "http://revision3.com/api/oembed/",
|
||||
"title": "Revision3"
|
||||
},
|
||||
{
|
||||
"url": "http://*.scribd.com/*",
|
||||
"url_re": "scribd\\.com/.+",
|
||||
"example_url": "http://www.scribd.com/doc/17896323/Indian-Automobile-industryPEST",
|
||||
"endpoint_url": "http://www.scribd.com/services/oembed",
|
||||
"title": "Scribd"
|
||||
},
|
||||
{
|
||||
"url": "http://*.viddler.com/explore/*",
|
||||
"url_re": "viddler\\.com/explore/.*/videos/\\w+/?",
|
||||
"example_url": "http://www.viddler.com/explore/engadget/videos/14/",
|
||||
"endpoint_url": "http://lab.viddler.com/services/oembed/",
|
||||
"title": "Viddler Video"
|
||||
},
|
||||
{
|
||||
"url": "http://www.vimeo.com/* and http://www.vimeo.com/groups/*/videos/*",
|
||||
"url_re": "vimeo\\.com/.*",
|
||||
"example_url": "http://www.vimeo.com/1211060",
|
||||
"endpoint_url": "http://www.vimeo.com/api/oembed.json",
|
||||
"title": "Vimeo"
|
||||
},
|
||||
{
|
||||
"url": "http://*.youtube.com/watch*",
|
||||
"url_re": "youtube\\.com/watch.+v=[\\w-]+&?",
|
||||
"example_url": "http://www.youtube.com/watch?v=vk1HvP7NO5w",
|
||||
"endpoint_url": "http://www.youtube.com/oembed",
|
||||
"title": "YouTube"
|
||||
},
|
||||
{
|
||||
"url": "http://dotsub.com/view/*",
|
||||
"url_re": "dotsub\\.com/view/[-\\da-zA-Z]+$",
|
||||
"example_url": "http://dotsub.com/view/10e3cb5e-96c7-4cfb-bcea-8ab11e04e090",
|
||||
"endpoint_url": "http://dotsub.com/services/oembed",
|
||||
"title": "dotSUB.com"
|
||||
},
|
||||
{
|
||||
"url": "http://yfrog.(com|ru|com.tr|it|fr|co.il|co.uk|com.pl|pl|eu|us)/*",
|
||||
"url_re": "yfrog\\.(com|ru|com\\.tr|it|fr|co\\.il|co\\.uk|com\\.pl|pl|eu|us)/[a-zA-Z0-9]+$",
|
||||
"example_url": "http://yfrog.com/0wgvcpj",
|
||||
"endpoint_url": "http://www.yfrog.com/api/oembed",
|
||||
"title": "YFrog"
|
||||
},
|
||||
{
|
||||
"url": "http://*.clikthrough.com/theater/video/*",
|
||||
"url_re": "clikthrough\\.com/theater/video/\\d+$",
|
||||
"example_url": "http://www.clikthrough.com/theater/video/55",
|
||||
"endpoint_url": "http://clikthrough.com/services/oembed",
|
||||
"title": "Clikthrough"
|
||||
},
|
||||
{
|
||||
"url": "http://*.kinomap.com/*",
|
||||
"url_re": "kinomap\\.com/.+",
|
||||
"example_url": "http://www.kinomap.com/kms-vzkpc7",
|
||||
"endpoint_url": "http://www.kinomap.com/oembed",
|
||||
"title": "Kinomap"
|
||||
},
|
||||
{
|
||||
"url": "http://*.photobucket.com/albums/*|http://*.photobucket.com/groups/*",
|
||||
"url_re": "photobucket\\.com/(albums|groups)/.+$",
|
||||
"example_url": "http://img.photobucket.com/albums/v211/JAV123/Michael%20Holland%20Candle%20Burning/_MG_5661.jpg",
|
||||
"endpoint_url": "http://photobucket.com/oembed",
|
||||
"title": "Photobucket"
|
||||
}
|
||||
]
|
|
@ -2,21 +2,24 @@ from __future__ import division # Use true division
|
|||
|
||||
from django.utils.html import escape
|
||||
|
||||
from .embeds import get_embed
|
||||
from .embeds.embed import get_embed
|
||||
|
||||
|
||||
def embed_to_frontend_html(url):
|
||||
embed = get_embed(url)
|
||||
if embed is not None:
|
||||
# Work out ratio
|
||||
if embed.width and embed.height:
|
||||
ratio = str(embed.height / embed.width * 100) + "%"
|
||||
else:
|
||||
ratio = "0"
|
||||
try:
|
||||
embed = get_embed(url)
|
||||
if embed is not None:
|
||||
# Work out ratio
|
||||
if embed.width and embed.height:
|
||||
ratio = str(embed.height / embed.width * 100) + "%"
|
||||
else:
|
||||
ratio = "0"
|
||||
|
||||
# Build html
|
||||
return '<div style="padding-bottom: %s;" class="responsive-object">%s</div>' % (ratio, embed.html)
|
||||
else:
|
||||
# Build html
|
||||
return '<div style="padding-bottom: %s;" class="responsive-object">%s</div>' % (ratio, embed.html)
|
||||
else:
|
||||
return ''
|
||||
except:
|
||||
return ''
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django import template
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from wagtail.wagtailembeds.embeds import get_embed
|
||||
from wagtail.wagtailembeds.embed.embeds import get_embed
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
@ -10,9 +10,12 @@ register = template.Library()
|
|||
@register.filter
|
||||
def embed(url, max_width=None):
|
||||
embed = get_embed(url, max_width=max_width)
|
||||
if embed is not None:
|
||||
return mark_safe(embed.html)
|
||||
else:
|
||||
try:
|
||||
if embed is not None:
|
||||
return mark_safe(embed.html)
|
||||
else:
|
||||
return ''
|
||||
except:
|
||||
return ''
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.test import TestCase
|
||||
from django.test import TestCasez
|
||||
|
||||
from .embeds import get_embed
|
||||
|
||||
|
|
|
@ -5,6 +5,10 @@ from wagtail.wagtailadmin.modal_workflow import render_modal_workflow
|
|||
from wagtail.wagtailembeds.forms import EmbedForm
|
||||
from wagtail.wagtailembeds.format import embed_to_editor_html
|
||||
|
||||
from wagtail.wagtailembeds.embeds.oembed_api import NotImplementedOembedException
|
||||
from wagtail.wagtailembeds.embeds.embed import EmbedlyException, AccessDeniedEmbedlyException, NotFoundEmbedlyException
|
||||
|
||||
|
||||
|
||||
def chooser(request):
|
||||
form = EmbedForm()
|
||||
|
@ -19,18 +23,27 @@ def chooser_upload(request):
|
|||
form = EmbedForm(request.POST, request.FILES)
|
||||
|
||||
if form.is_valid():
|
||||
embed_html = embed_to_editor_html(form.cleaned_data['url'])
|
||||
if embed_html != "":
|
||||
try:
|
||||
embed_html = embed_to_editor_html(form.cleaned_data['url'])
|
||||
return render_modal_workflow(
|
||||
request, None, 'wagtailembeds/chooser/embed_chosen.js',
|
||||
{'embed_html': embed_html}
|
||||
)
|
||||
else:
|
||||
except Exception as e :
|
||||
#print e
|
||||
#import traceback
|
||||
#traceback.print_exc()
|
||||
errors = form._errors.setdefault('url', ErrorList())
|
||||
if not hasattr(settings, 'EMBEDLY_KEY'):
|
||||
errors.append('Please set EMBEDLY_KEY in your settings')
|
||||
if type(e) == NotImplementedOembedException:
|
||||
errors.append("This URL is not supported by an oembed provider. You may try embedding it using Embedly by setting a propery EMBEDLY_KEY in your settings.")
|
||||
elif type(e) == AccessDeniedEmbedlyException:
|
||||
errors.append("There seems to be a problem with your embedly API key. Please check your settings.")
|
||||
elif type(e) == NotFoundEmbedlyException:
|
||||
errors.append("The URL you are trying to embed cannot be found.")
|
||||
elif type(e) == EmbedlyException:
|
||||
errors.append("There seems to be an error with Embedly while trying to embed this URL. Please try again later.")
|
||||
else:
|
||||
errors.append('This URL is not recognised')
|
||||
errors.append(str(e) )
|
||||
return render_modal_workflow(request, 'wagtailembeds/chooser/chooser.html', 'wagtailembeds/chooser/chooser.js', {
|
||||
'form': form,
|
||||
})
|
||||
|
|
Ładowanie…
Reference in New Issue