Pre-merge

This commit is contained in:
Fergal Moran
2015-11-08 19:45:45 +00:00
28 changed files with 345 additions and 196 deletions

View File

@@ -19,10 +19,9 @@ ADD . /code/
RUN apt-get update && apt-get install -y sox lame vim \
libboost-program-options-dev libsox-fmt-mp3 postgresql-client rsync openssh-client
RUN pip uninstall azure
RUN pip install -r requirements.txt
RUN adduser --disabled-password --gecos '' djworker
RUN chown djworker /files -R
RUN chown djworker /srv/logs -R
RUN export PATH=$PATH:/mnt/bin/
RUN export PATH=$PATH:/mnt/bin/

View File

@@ -6,6 +6,7 @@ from dss import settings
from spa import models
from spa.models import Activity, Message
from spa.models.activity import ActivityDownload, ActivityPlay
from spa.models.blog import Blog
from spa.models.genre import Genre
from spa.models.notification import Notification
from spa.models.show import Show
@@ -509,3 +510,10 @@ class ShowSerializer(serializers.ModelSerializer):
)
"""
class BlogSerializer(serializers.ModelSerializer):
slug = serializers.ReadOnlyField(required=False)
user = InlineUserProfileSerializer(read_only=True)
class Meta:
model = Blog

View File

@@ -23,6 +23,7 @@ router.register(r'activity', views.ActivityViewSet, base_name='activity')
router.register(r'genre', views.GenreViewSet, base_name='genre')
router.register(r'messages', views.MessageViewSet, base_name='messages')
router.register(r'shows', views.ShowViewSet, base_name='shows')
router.register(r'blog', views.BlogViewSet, base_name='shows')
class DebugView(APIView):

View File

@@ -20,6 +20,7 @@ from api import serializers
from dss import settings
from spa import tasks
from spa.models import Message
from spa.models.blog import Blog
from spa.models.genre import Genre
from spa.models.activity import ActivityPlay
from spa.models.mix import Mix
@@ -217,7 +218,7 @@ class PartialMixUploadView(views.APIView):
(
tasks.create_waveform_task.s(input_file, uid) |
tasks.upload_to_cdn_task.subtask(('mp3', uid, 'mixes'), immutable=True) |
tasks.upload_to_cdn_task.subtask(('png', uid, 'waveforms'), immutable=True) |
tasks.upload_to_cdn_task.subtask (('png', uid, 'waveforms'), immutable=True) |
tasks.notify_subscriber.subtask((session_id, uid), immutable=True)
).delay()
logger.debug("Waveform task started")
@@ -348,3 +349,12 @@ class ShowViewSet(viewsets.ModelViewSet):
return Response(status=HTTP_400_BAD_REQUEST, data='Performer not found')
except Exception as ex:
return Response(status=HTTP_500_INTERNAL_SERVER_ERROR, data=ex)
class BlogViewSet(viewsets.ModelViewSet):
queryset = Blog.objects.all()
serializer_class = serializers.BlogSerializer
lookup_field = 'slug'
def perform_create(self, serializer):
serializer.save(user=self.request.user.userprofile)

View File

@@ -1,6 +1,5 @@
import requests
from bs4 import BeautifulSoup
from requests.packages.urllib3.connection import ConnectionError
from dss import settings

View File

@@ -1,5 +1,3 @@
import os
import logging

View File

@@ -1,41 +0,0 @@
import os
DEBUG = True
if os.name == 'posix':
DSS_TEMP_PATH = "/tmp/"
DSS_LAME_PATH = "sox"
DSS_WAVE_PATH = "wav2png"
else:
DSS_TEMP_PATH = "d:\\temp\\"
DSS_LAME_PATH = "D:\\Apps\\lame\\lame.exe"
DSS_WAVE_PATH = "d:\\Apps\\waveformgen.exe"
DATABASE_NAME = 'deepsouthsounds'
DATABASE_USER = 'deepsouthsounds'
DATABASE_PASSWORD = ''
# DATABASE_HOST = ''
PIPELINE_YUI_BINARY = ""
FACEBOOK_APP_SECRET = ''
JS_SETTINGS = {
'CHAT_HOST': "ext-test.deepsouthsounds.com:8081",
'API_URL': "/api/v1/",
'LIVE_STREAM_URL': "radio.deepsouthsounds.com",
'LIVE_STREAM_PORT': "8000",
'LIVE_STREAM_MOUNT': "mp3",
'DEFAULT_AUDIO_VOLUME': "50",
'SM_DEBUG_MODE': DEBUG,
'LIVE_STREAM_INFO_URL': "radio.deepsouthsounds.com:8000/mp3"
}
"""
WAVEFORM_URL = 'http://waveforms.podnoms.com/'
IMAGE_URL = 'http://images.podnoms.com/'
STATIC_URL = 'http://static.podnoms.com/'
"""
IMAGE_URL = 'http://ext-test.deepsouthsounds.com:8000/media/'
GOOGLE_ANALYTICS_CODE = ''
SENDFILE_BACKEND = 'sendfile.backends.development'
#SENDFILE_BACKEND = 'sendfile.backends.xsendfile'
#SENDFILE_BACKEND = 'sendfile.backends.nginx'

55
dss/localsettings.py Normal file
View File

@@ -0,0 +1,55 @@
import os
from dss import devsettings
DEBUG = True
DSS_TEMP_PATH = os.environ.get('DSS_TEMP_PATH', '/tmp/')
DSS_LAME_PATH = os.environ.get('DSS_LAME_PATH', '/usr/bin/sox')
DSS_WAVE_PATH = os.environ.get('DSS_WAVE_PATH',
'/home/fergalm/Dropbox/development/deepsouthsounds.com/dss.lib/wav2png/bin/Linux/wav2png')
GEOIP_PATH = os.environ.get('GEOIP_PATH', '/home/fergalm/Dropbox/Private/deepsouthsounds.com/working/geolite')
DATABASE_PASSWORD = os.environ.get('DATABASE_PASSWORD', 'deepsouthsounds')
DATABASE_NAME = os.environ.get('DATABASE_NAME', 'deepsouthsounds')
DATABASE_USER = os.environ.get('DATABASE_USER', 'deepsouthsounds')
DATABASE_HOST = os.environ.get('DATABASE_HOST', 'localhost')
STATIC_URL = '/assets/'
MEDIA_ROOT = os.environ.get('MEDIA_ROOT', '/home/fergalm/Dropbox/development/deepsouthsounds.com/cache/media')
STATIC_ROOT = os.environ.get('STATIC_ROOT', '/home/fergalm/Dropbox/development/deepsouthsounds.com/cache/static')
CACHE_ROOT = os.environ.get('CACHE_ROOT', '/home/fergalm/Dropbox/development/deepsouthsounds.com/cache/cache')
MEDIA_URL = os.environ.get('MEDIA_URL', 'http://localhost/DSSMedia/') # '{0}media/'.format(CDN_URL)
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
BROKER_URL = os.environ.get('BROKER_URL', 'amqp://guest:guest@localhost:5672//')
CELERY_ACCEPT_CONTENT = ['pickle', 'msgpack', 'json']
SECRET_KEY = os.environ.get('SECRET_KEY', devsettings.SECRET_KEY)
LIVE_ENABLED = os.environ.get('LIVE_ENABLED', False)
ICE_HOST = os.environ.get('ICE_HOST', 'localhost')
ICE_MOUNT = os.environ.get('ICE_MOUNT =', 'dss')
ICE_PORT = os.environ.get('ICE_PORT', 8000)
RADIO_HOST = os.environ.get('RADIO_HOST', 'localhost')
RADIO_PORT = os.environ.get('RADIO_PORT', 8888)
MANDRILL_API_KEY = os.environ.get('MANDRILL_API_KEY', '')
SOCIAL_AUTH_FACEBOOK_KEY = os.environ.get('SOCIAL_AUTH_FACEBOOK_KEY', devsettings.SOCIAL_AUTH_FACEBOOK_KEY)
SOCIAL_AUTH_FACEBOOK_SECRET = os.environ.get('SOCIAL_AUTH_FACEBOOK_SECRET', devsettings.SOCIAL_AUTH_FACEBOOK_SECRET)
SOCIAL_AUTH_TWITTER_KEY = os.environ.get('SOCIAL_AUTH_TWITTER_KEY', devsettings.SOCIAL_AUTH_TWITTER_KEY)
SOCIAL_AUTH_TWITTER_SECRET = os.environ.get('SOCIAL_AUTH_TWITTER_SECRET', devsettings.SOCIAL_AUTH_TWITTER_SECRET)
SOCIAL_AUTH_GOOGLE_OAUTH_KEY = os.environ.get('SOCIAL_AUTH_GOOGLE_OAUTH_KEY', devsettings.SOCIAL_AUTH_GOOGLE_OAUTH_KEY)
SOCIAL_AUTH_GOOGLE_OAUTH_SECRET = os.environ.get('SOCIAL_AUTH_GOOGLE_OAUTH_SECRET', devsettings.SOCIAL_AUTH_GOOGLE_OAUTH_SECRET)
SOCIAL_AUTH_GOOGLE_PLUS_KEY = os.environ.get('SOCIAL_AUTH_GOOGLE_PLUS_KEY', devsettings.SOCIAL_AUTH_GOOGLE_PLUS_KEY)
SOCIAL_AUTH_GOOGLE_PLUS_SECRET = os.environ.get('SOCIAL_AUTH_GOOGLE_PLUS_SECRET', devsettings.SOCIAL_AUTH_GOOGLE_PLUS_SECRET)
DSS_DB_BACKUP_KEY = os.environ.get('DSS_DB_BACKUP_KEY', devsettings.DSS_DB_BACKUP_KEY)
DSS_DB_BACKUP_SECRET = os.environ.get('DSS_DB_BACKUP_SECRET', devsettings.DSS_DB_BACKUP_SECRET)
DSS_DB_BACKUP_TOKEN = os.environ.get('DSS_DB_BACKUP_TOKEN', devsettings.DSS_DB_BACKUP_TOKEN)
AZURE_ACCOUNT_KEY = os.environ.get('AZURE_ACCOUNT_KEY', devsettings.AZURE_ACCOUNT_KEY)

View File

@@ -1,91 +0,0 @@
iPIPELINE_TEMPLATE_FUNC = "_.template"
PIPELINE_COMPILERS = (
'pipeline.compilers.coffee.CoffeeScriptCompiler',
)
PIPELINE_CSS = {
'css': {
'source_filenames': (
'css/dss.overrides.css',
'css/ace/dropzone.css',
'css/ace/uncompressed/jquery.gritter.css',
'css/ace/uncompressed/bootstrap.css',
'css/ace/uncompressed/ace.css',
'css/ace/uncompressed/ace-ie.css',
'css/ace/uncompressed/ace-skins.css',
'css/ace/uncompressed/font-awesome.css',
'css/ace/uncompressed/fullcalendar.css',
'css/ace/uncompressed/bootstrap-editable.css',
'css/jasny-bootstrap.css',
'css/select2.css',
'css/jquery.fileupload-ui.css',
'css/peneloplay.css',
'css/toastr.css',
'css/dss.main.css',
),
'output_filename': 'css/site.css'
}
}
PIPELINE_JS = {
'templates': {
'source_filenames': (
'js/dss/templates/*.jst',
),
'variant': 'datauri',
'output_filename': 'js/t.js',
},
'lib': {
'source_filenames': (
'js/lib/jquery.js',
'js/lib/jquery-ui.js',
'js/lib/moment.js',
'js/lib/typeahead.js',
'js/lib/sm/soundmanager2.js',
'js/lib/underscore.js',
'js/lib/underscore.templatehelpers.js',
'js/lib/backbone.js',
'js/lib/backbone.syphon.js',
'js/lib/backbone.associations.js',
'js/lib/backbone.marionette.js',
'js/lib/ace/uncompressed/bootstrap.js',
'js/lib/ace/uncompressed/ace.js',
'js/lib/ace/uncompressed/ace-elements.js',
'js/lib/ace/uncompressed/select2.js',
'js/lib/ace/uncompressed/fuelux/fuelux.wizard.js',
'js/lib/ace/ace/elements.wizard.js',
'js/lib/ace/uncompressed/bootstrap-wysiwyg.js',
'js/lib/ace/uncompressed/jquery.gritter.js',
'js/lib/ace/uncompressed/dropzone.js',
'js/lib/ace/uncompressed/fullcalendar.js',
'js/lib/ace/uncompressed/x-editable/bootstrap-editable.js',
'js/lib/ace/uncompressed/x-editable/ace-editable.js',
'js/lib/ajaxfileupload.js',
'js/lib/jasny.fileinput.js',
'js/lib/jquery.fileupload.js',
'js/lib/jquery.fileupload-process.js',
'js/lib/jquery.fileupload-audio.js',
'js/lib/jquery.fileupload-video.js',
'js/lib/jquery.fileupload-validate.js',
'js/lib/jquery.fileupload-ui.js',
'js/lib/jquery.fileupload-image.js',
'js/lib/jquery.iframe-transport.js',
'js/lib/jquery.ui.widget.js',
'js/lib/toastr.js',
'js/dss/*.coffee',
'js/dss/**/*.coffee',
'js/dss/apps/**/**/*.coffee',
),
'output_filename': 'js/a.js',
},
}

View File

@@ -19,7 +19,6 @@ SOCIAL_AUTH_PIPELINE = (
'social.pipeline.user.get_username',
'social.pipeline.social_auth.associate_by_email',
'social.pipeline.user.create_user',
'spa.pipeline.save_profile',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'

View File

@@ -4,6 +4,7 @@ import mimetypes
from datetime import timedelta
from django.core.urlresolvers import reverse_lazy
from django.conf import global_settings
from dss import storagesettings
from utils import here
@@ -168,12 +169,7 @@ if DEBUG:
REALTIME_HEADERS = {
'content-type': 'application/json'
}
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
if 'test' in sys.argv:
try:
from .test_settings import *
except ImportError:
pass
REST_FRAMEWORK = {
# Use hyperlinked styles by default.
@@ -211,3 +207,31 @@ JWT_AUTH = {
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=30),
}
""" static settings """
CDN_URL = storagesettings.AZURE_ITEM_BASE_URL
MIXIMAGE_URL = '{0}miximages/'.format(CDN_URL)
WAVEFORM_URL = '{0}waveforms/'.format(CDN_URL)
STREAM_URL = '{0}mixes/'.format(CDN_URL)
AUDIO_URL = '{0}mixes/'.format(CDN_URL)
NOTIFICATIONS_FROM_ADDRESS = "admin@deepsouthsounds.com"
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'cache-control',
'accept',
'origin',
'authorization',
'upload-hash',
'session-id',
'auth-backend',
'x-csrftoken'
)
""" End static settings """

6
dss/storagesettings.py Normal file
View File

@@ -0,0 +1,6 @@
from dss import localsettings
AZURE_ACCOUNT_NAME = 'dsscdn'
AZURE_CONTAINER = 'media'
AZURE_ACCOUNT_KEY = localsettings.AZURE_ACCOUNT_KEY
AZURE_ITEM_BASE_URL = 'https://dsscdn.blob.core.windows.net/'

View File

@@ -1,10 +0,0 @@
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'dss_test.db',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}

View File

@@ -11,7 +11,8 @@ urlpatterns = patterns(
url(r'^admin/', include(admin.site.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
(r'^grappelli/', include('grappelli.urls')),
(r'^social/', include('spa.social.urls')),
(r'^__redir/blog/', include('spa.blog.urls')),
(r'^__redir/social/', include('spa.social.urls')),
(r'^arges/', include('spa.social.urls')),
url(r'', include('user_sessions.urls', 'user_sessions')),
url(r'^', include('api.urls')),

7
spa/blog/urls.py Executable file
View File

@@ -0,0 +1,7 @@
from django.conf.urls import patterns, url
urlpatterns = patterns(
'',
url(r'^blog/(?P<slug>[\w\d_.-]+)/?$', 'spa.blog.views.entry', name='blog_entry_slug'),
url(r'^$', 'spa.blog.views.index', name='blog_index')
)

58
spa/blog/views.py Executable file
View File

@@ -0,0 +1,58 @@
import urllib.request, urllib.error, urllib.parse
import logging
from django.conf.urls import url
from django.contrib.sites.models import Site
from django.core.urlresolvers import resolve
from django.http import Http404
from django.shortcuts import render_to_response
from django.template.context import RequestContext
import requests
from allauth.socialaccount.models import SocialToken
from core.utils.url import wrap_full
from dss import settings
from spa.models import Playlist, Blog
from spa.models.mix import Mix
from spa.models.userprofile import UserProfile
logger = logging.getLogger(__name__)
"""
Handles callbacks from non javascript browsers
"""
def _getPayload(request):
return {
"app_id": settings.FACEBOOK_APP_ID,
"site_url": 'http://%s' % Site.objects.get_current().domain,
"site_image_url": '%s/img/dss-large.png' % settings.STATIC_URL,
}
def entry(request, slug):
try:
blog = Blog.objects.get(slug=slug)
extras = {
"content": blog.body,
}
payload = dict(list(_getPayload(request).items()) + list(extras.items()))
response = render_to_response(
'blog/entry.html',
payload,
context_instance=RequestContext(request)
)
return response
except Blog.DoesNotExist:
raise Http404
except Exception as ex:
logger.error(ex)
def index(request):
response = render_to_response(
"blog/index.html",
_getPayload(request),
context_instance=RequestContext(request))
return response

View File

@@ -1,7 +1,7 @@
from azure.storage.blob import BlobService
import urllib.request, urllib.error, urllib.parse
from allauth.socialaccount.models import SocialAccount
from azure.storage import BlobService
from django.core.files.base import File
from django.core.files.temp import NamedTemporaryFile
from django.core.management.base import NoArgsCommand

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('spa', '0016_remove_show_recurrence_rrule'),
]
operations = [
migrations.CreateModel(
name='Blog',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
('object_created', models.DateTimeField(auto_now_add=True)),
('object_updated', models.DateTimeField(auto_now=True, db_index=True)),
('date_created', models.DateField(auto_now=True)),
('title', models.CharField(max_length=1024)),
('body', models.TextField()),
('user', models.ForeignKey(blank=True, to='spa.UserProfile', null=True)),
],
options={
'abstract': False,
},
),
]

View File

@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('spa', '0017_blog'),
]
operations = [
migrations.AddField(
model_name='blog',
name='published',
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('spa', '0018_blog_published'),
]
operations = [
migrations.AddField(
model_name='blog',
name='slug',
field=models.SlugField(default='arse'),
preserve_default=False,
),
]

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('spa', '0019_blog_slug'),
]
operations = [
migrations.CreateModel(
name='BlogComment',
fields=[
('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')),
('object_created', models.DateTimeField(auto_now_add=True)),
('object_updated', models.DateTimeField(auto_now=True, db_index=True)),
('comment', models.CharField(max_length=1024)),
('date_created', models.DateField(auto_now_add=True)),
('blog', models.ForeignKey(to='spa.Blog')),
('user', models.ForeignKey(null=True, to='spa.UserProfile', blank=True)),
],
options={
'abstract': False,
},
),
]

View File

@@ -16,3 +16,4 @@ from .release import Release
from .playlist import Playlist
from .message import Message
from .show import Show
from .blog import Blog

26
spa/models/blog.py Normal file
View File

@@ -0,0 +1,26 @@
from core.utils.url import unique_slugify
from spa.models import BaseModel, UserProfile
from django.db import models
class Blog(BaseModel):
user = models.ForeignKey(UserProfile, null=True, blank=True)
date_created = models.DateField(auto_now=True)
published = models.BooleanField(default=False)
slug = models.SlugField()
title = models.CharField(max_length=1024)
body = models.TextField()
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
if not self.id:
self.slug = unique_slugify(self, self.title)
super(Blog, self).save(force_insert, force_update, using, update_fields)
class BlogComment(BaseModel):
blog = models.ForeignKey(Blog)
user = models.ForeignKey(UserProfile, null=True, blank=True)
comment = models.CharField(max_length=1024)
date_created = models.DateField(auto_now_add=True)

View File

@@ -103,7 +103,7 @@ class Mix(BaseModel):
self.clean_image('mix_image', Mix)
# Check for the unlikely event that the waveform has been generated
if cdn.file_exists('{0}{1}.png'.format(localsettings.WAVEFORM_URL, self.uid)):
if cdn.file_exists('{0}{1}.png'.format(settings.WAVEFORM_URL, self.uid)):
self.waveform_generated = True
try:
self.duration = mp3_length(self.get_absolute_path())
@@ -153,14 +153,13 @@ class Mix(BaseModel):
def get_waveform_url(self, waveform_type=""):
# TODO: Design better flow for this sort of thing
if not self.waveform_generated and cdn.file_exists('{0}{1}.png'.format(localsettings.WAVEFORM_URL, self.uid)):
if not self.waveform_generated and cdn.file_exists('{0}{1}.png'.format(settings.WAVEFORM_URL, self.uid)):
self.waveform_generated = True
self.save()
if self.waveform_generated:
waveform_root = localsettings.WAVEFORM_URL \
if hasattr(localsettings,
'WAVEFORM_URL') else "%swaveforms" % settings.MEDIA_URL
waveform_root = settings.WAVEFORM_URL \
if hasattr(settings, 'WAVEFORM_URL') else "%swaveforms" % settings.MEDIA_URL
ret = "%s/%s%s.%s" % (waveform_root, self.uid, waveform_type, "png")
return url.urlclean(ret)

View File

@@ -1,34 +0,0 @@
from django.core.files.base import ContentFile
from requests import request, ConnectionError
def save_profile(backend, user, response, is_new, *args, **kwargs):
if backend.name == 'google-oauth2':
if response.get('image') and response['image'].get('url'):
url = response['image'].get('url')
profile = user.userprofile
try:
response = request('GET', url)
response.raise_for_status()
except ConnectionError:
pass
else:
profile.avatar_image.save('',
ContentFile(response.content),
save=False)
profile.save()
elif backend.name == 'facebook':
profile = user.userprofile
url = 'http://graph.facebook.com/{0}/picture'.format(response['id'])
try:
response = request('GET', url, params={'type': 'large'})
response.raise_for_status()
except ConnectionError:
pass
else:
profile.avatar_image.save('',
ContentFile(response.content),
save=False
)
profile.save()

18
templates/blog/entry.html Normal file
View File

@@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:og="http://ogp.me/ns#"
xmlns:fb="https://www.facebook.com/2008/fbml">
<head>
<meta property="fb:app_id" content="{{ app_id }}"/>
<meta property="og:url" content="{{ mix_url }}/"/>
<meta property="og:site_name" content="Deep South Sounds"/>
<meta property="og:type" content="deepsouthsounds:blog"/>
<meta property="og:title" content="{{ title }}"/>
<meta property="og:description" content="{{ description }}"/>
<meta property="og:image" content="{{ image }}"/>
</head>
<body>
{{ content }}
</body>
</html>

19
templates/blog/index.html Normal file
View File

@@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:og="http://ogp.me/ns#"
xmlns:fb="https://www.facebook.com/2008/fbml">
<head>
<meta property="fb:app_id" content="{{ app_id }}"/>
<meta property="og:url" content="{{ mix_url }}/"/>
<meta property="og:site_name" content="Deep South Sounds"/>
<meta property="og:type" content="deepsouthsounds:blog"/>
<meta property="og:title" content="{{ title }}"/>
<meta property="og:description" content="{{ description }}"/>
<meta property="og:image" content="{{ image }}"/>
</head>
<body>
<h1>Blog Index</h1>
{{ content }}
</body>
</html>