...
 
Commits (12)
ivatar / libravatar
===================
Pipeline and coverage status
============================
[![pipeline status](https://git.linux-kernel.at/oliver/ivatar/badges/master/pipeline.svg)](https://git.linux-kernel.at/oliver/ivatar/commits/master)
[![coverage report](https://git.linux-kernel.at/oliver/ivatar/badges/master/coverage.svg)](http://git.linux-kernel.at/oliver/ivatar/commits/master)
Reports / code documentation
============================
- [Coverage HTML report](http://oliver.git.linux-kernel.at/ivatar)
- [Code documentation (autogenerated, pycco)](http://oliver.git.linux-kernel.at/ivatar/pycco/)
Authors and contributors
========================
Lead developer/Owner: Oliver Falk (aka ofalk or falko) - https://git.linux-kernel.at/oliver
Operations: Michal Novotny (aka clime)
QA: Tristan Le Guern (aka tleguern)
Frontend developer: Niklas Poslovski (aka nipos)
Organisation/Meeting moderation: Lars Kruse (aka sumpfralle)
Initial developer: François Marier - https://fmarier.org/
......@@ -187,3 +187,7 @@ CACHES = {
],
}
}
# This is 5 minutes caching for generated/resized images,
# so the sites don't hit ivatar so much
CACHE_IMAGES_MAX_AGE = 5 * 60
......@@ -816,12 +816,16 @@ class UploadLibravatarExportView(SuccessMessageMixin, FormView):
def form_valid(self, form):
data = self.request.FILES['export_file']
items = libravatar_read_gzdata(data.read())
# DEBUG print(items)
return render(self.request, 'choose_libravatar_export.html', {
'emails': items['emails'],
'photos': items['photos'],
})
try:
items = libravatar_read_gzdata(data.read())
# DEBUG print(items)
return render(self.request, 'choose_libravatar_export.html', {
'emails': items['emails'],
'photos': items['photos'],
})
except Exception as e:
messages.error(self.request, _('Unable to parse file: %s' % e))
return HttpResponseRedirect(reverse_lazy('upload_export'))
@method_decorator(login_required, name='dispatch')
......
body{font-family:'Source Sans Pro',Helvetica,Arial,sans-serif;color:#525252}.btn{border-bottom-width:3px;box-sizing:border-box;font-family:'Montserrat',sans-serif;text-transform:uppercase;background:#ff8800;overflow:hidden;position:relative;-webkit-transition:all .3s;-moz-transition:all .3s;-ms-transition:all .3s;transition:all .3s}.btn.btn-default{color:#ffa033;border-color:#ffa033;background:none}.btn.btn-primary{border-color:#b35f00}.btn:hover,.btn:active,.btn:focus{background:none;border-color:#cc6d00;color:#cc6d00}.btn:hover:after,.btn:active:after,.btn:focus:after{top:50%}.btn:after{content:'';position:absolute;z-index:-1;width:150%;height:200%;top:-190%;left:50%;background:#ffb866;-webkit-transform:translateX(-50%) translateY(-50%) skew(0, 5deg);-moz-transform:translateX(-50%) translateY(-50%) skew(0, 5deg);-ms-transform:translateX(-50%) translateY(-50%) skew(0, 5deg);transform:translateX(-50%) translateY(-50%) skew(0, 5deg);-webkit-transition:all .5s ease-out;-moz-transition:all .5s ease-out;-ms-transition:all .5s ease-out;transition:all .5s ease-out}.btn.btn-block:after{height:250%;width:200%;-webkit-transform:translateX(-50%) translateY(-50%) skew(0, 2deg);-moz-transform:translateX(-50%) translateY(-50%) skew(0, 2deg);-ms-transform:translateX(-50%) translateY(-50%) skew(0, 2deg);transform:translateX(-50%) translateY(-50%) skew(0, 2deg)}.hero{background-color:#ff8800;color:#fff;padding:90px 0 40px}.hero h1{font-weight:600;font-size:6em;color:rgba(255,255,255,0.5)}.hero h2{font-weight:200;font-size:30px;margin-bottom:30px}.hero small{color:rgba(0,0,0,0.4)}.hero .btn{display:inline-block}.hero .btn.btn-default{color:#ffbc70;border-color:#ffbc70;background:none}.hero .btn.btn-primary{border-color:#fff}.hero .btn:hover,.hero .btn:active,.hero .btn:focus{border-color:#fff;color:#995200}.hero .btn:after{background:rgba(255,255,255,0.5)}.hero .container{position:relative;z-index:10}.social{background-color:#ff8800;padding:30px 0 140px}.social ul{list-style:none;padding:0;margin:0}.social ul li{float:left;margin-right:15px;width:100px}.clipper,.clipper-footer{background-color:#fff;height:110px;width:100%;position:relative;top:-40px;-webkit-transform:skew(0, 2deg);-moz-transform:skew(0, 2deg);-ms-transform:skew(0, 2deg);transform:skew(0, 2deg);pointer-events:none;z-index:1}.clipper-footer{top:0}section.content{position:relative;top:-100px;margin-bottom:-100px;z-index:10}section.content h1,section.content h2,section.content h3,section.content h4,section.content h5,section.content h6{color:#cc6d00}section.content h2{font-weight:200;font-size:40px}section.content section{margin-bottom:20px;margin-top:20px}section.content .container>hr{-webkit-transform:skew(0, 2deg);-moz-transform:skew(0, 2deg);-ms-transform:skew(0, 2deg);transform:skew(0, 2deg);margin-top:80px;margin-bottom:40px}footer{background-color:#dddddd;color:#888888;padding:100px 0 40px;margin-top:-40px}footer .pull-left{margin-right:20px}footer .logo{float:left;display:inline-block;margin-right:5px;margin-top:-8px}footer .logo .circle{stroke:#888888;stroke-width:7;fill:none}footer .logo .polygon{fill:#888888}@media (max-width:768px){.hero{padding:50px 0 30px}.hero h1{font-size:4em}.social{padding:30px 0 100px}.btn{margin-bottom:5px}section.content section{margin-bottom:50px}}.color{display:inline-block;border-radius:50%;height:20px;width:20px}.color.blue{background-color:#36b7d7}.color.green{background-color:#3aa850}.color.red{background-color:#f7645e}.color.black{background-color:#525252}.navbar-tortin{border:0;background-color:#ff8800;color:#FFFFFF;border-radius:0}.form-control{border-bottom-width:3px;box-sizing:border-box;font-family:'Montserrat',sans-serif;overflow:hidden;position:relative;-webkit-transition:all .3s;-moz-transition:all .3s;-ms-transition:all .3s;transition:all .3s;border-color:#ffa033;background:none}.form-control:focus{border-color:#cc6d00;box-shadow:none}.navbar-tortin .navbar-brand,.navbar-tortin .navbar-text,.navbar-tortin .navbar-nav>li>a,.navbar-tortin .navbar-link,.navbar-tortin .btn-link{color:#FFFFFF}.navbar-tortin .navbar-nav>.active>a,.navbar-tortin .navbar-nav>.active>a:focus,.navbar-tortin .navbar-nav>.active>a:hover,.navbar-tortin .navbar-nav>li>a:focus,.navbar-tortin .navbar-nav>li>a:hover,.navbar-tortin .navbar-link:hover,.navbar-tortin .btn-link:focus,.navbar-tortin .btn-link:hover,.navbar-tortin .navbar-nav>.open>a,.navbar-tortin .navbar-nav>.open>a:focus,.navbar-tortin .navbar-nav>.open>a:hover{background-color:#cc6d00}.navbar-tortin .navbar-toggle{border-color:#FFFFFF}.navbar-tortin .navbar-toggle:hover{background-color:#FFFFFF}.navbar-tortin .navbar-toggle .icon-bar{background-color:#FFFFFF}.navbar-tortin .navbar-toggle:hover .icon-bar{background-color:#ff8800}.navbar-tortin .navbar-collapse,.navbar-tortin .navbar-form{border:0}.dropdown-menu{background-color:#ff8800;border:1px solid #cc6d00}.dropdown-menu>li>a{color:#FFFFFF}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#cc6d00;color:#FFFFFF}.checkbox input,.radio input{display:none}.checkbox input+label,.radio input+label{padding-left:0}.checkbox input+label:before,.radio input+label:before{font-family:FontAwesome;display:inline-block;letter-spacing:5px;font-size:20px;color:#ff8800;vertical-align:middle}.checkbox input+label:before{content:"\f0c8"}.checkbox input:checked+label:before{content:"\f14a"}.radio input+label:before{content:"\f10c"}.radio input:checked+label:before{content:"\f192"}.uploadbtn:before{position:absolute;left:0;right:0;text-align:center;content:"Select file";font-family:'Montserrat',sans-serif}.jcrop-holder>div>div:nth-child(1){outline-width:2px;outline-style:solid;outline-color:#ff8800}@media (max-width:767px){.navbar-tortin .navbar-nav .open .dropdown-menu>li>a{color:#FFFFFF}.navbar-tortin .navbar-nav .open .dropdown-menu>li>a:hover{background-color:#cc6d00}.navbar-tortin .navbar-nav .open .dropdown-menu>.active>a,.navbar-tortin .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-tortin .navbar-nav .open .dropdown-menu>.active>a:hover{background-color:#cc6d00}}.panel-tortin{border-color:#ff8800;border-bottom-width:3px}.panel-tortin>.panel-heading{color:#fff;background-color:#ff8800;border-color:#ff8800;font-family:'Montserrat',sans-serif}.panel-tortin>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ff8800}.panel-tortin>.panel-heading .badge{color:#ff8800;background-color:#fff}.panel-tortin>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ff8800}.alert.alert-danger{background-color:#FFFFFF;color:#f7645e;border-color:#f7645e;border-bottom-width:3px;box-sizing:border-box;font-family:'Montserrat',sans-serif;overflow:hidden;position:relative}.input-group-addon{border-bottom-width:3px;box-sizing:border-box;font-family:'Montserrat',sans-serif;overflow:hidden;position:relative;border-color:#ffa033;background:none;width:auto;height:36px}.radio{color:#ff8800}input[type="radio"]:checked+label{font-weight:bold}.btn{border-radius:0 !important}
@import 'tortin.less';
@bg-hero:#ff8800;
.btn {
border-radius: 0px !important;
}
......@@ -34,7 +34,6 @@
</form>
</div>
<!-- TODO TODO TODO: I need better styling -->
{% if result %}
<hr/>
<h2>The following servers will be used for your domain</h2>
......@@ -44,8 +43,8 @@
</div>
<div class="panel-body">
{% if result.avatar_server_http %}
<a href="{{result.avatar_server_http}}">
<h4>{{result.avatar_server_http}}</h4>
<a href="http://{{result.avatar_server_http}}">
<h4>http://{{result.avatar_server_http}}</h4>
</a>
{% if result.avatar_server_http_ipv4 %}
<br><center>{{ result.avatar_server_http_ipv4 }}</center>
......@@ -66,8 +65,8 @@
</div>
<div class="panel-body">
{% if result.avatar_server_https %}
<a href="{{result.avatar_server_https}}">
<h4>{{result.avatar_server_https}}</h4>
<a href="https://{{result.avatar_server_https}}">
<h4>https://{{result.avatar_server_https}}</h4>
</a>
{% if result.avatar_server_https_ipv4 %}
<br><center>{{ result.avatar_server_https_ipv4 }}</center>
......
......@@ -8,4 +8,5 @@ from . views import CheckView, CheckDomainView
urlpatterns = [ # pylint: disable=invalid-name
url('check/', CheckView.as_view(), name='tools_check'),
url('check_domain/', CheckDomainView.as_view(), name='tools_check_domain'),
url('check_domain$', CheckDomainView.as_view(), name='tools_check_domain'),
]
......@@ -22,6 +22,7 @@ import pagan
from robohash import Robohash
from ivatar.settings import AVATAR_MAX_SIZE, JPEG_QUALITY, DEFAULT_AVATAR_SIZE
from ivatar.settings import CACHE_IMAGES_MAX_AGE
from . ivataraccount.models import ConfirmedEmail, ConfirmedOpenId
from . ivataraccount.models import pil_format, file_format
......@@ -147,9 +148,11 @@ class AvatarImageView(TemplateView):
data = BytesIO()
monsterdata.save(data, 'PNG', quality=JPEG_QUALITY)
data.seek(0)
return HttpResponse(
response = HttpResponse(
data,
content_type='image/png')
response['Cache-Control'] = 'max-age=%i' % CACHE_IMAGES_MAX_AGE
return response
if str(default) == 'robohash':
roboset = 'any'
......@@ -160,9 +163,11 @@ class AvatarImageView(TemplateView):
data = BytesIO()
robohash.img.save(data, format='png')
data.seek(0)
return HttpResponse(
response = HttpResponse(
data,
content_type='image/png')
response['Cache-Control'] = 'max-age=%i' % CACHE_IMAGES_MAX_AGE
return response
if str(default) == 'retro':
identicon = Identicon.render(kwargs['digest'])
......@@ -171,9 +176,11 @@ class AvatarImageView(TemplateView):
img = img.resize((size, size), Image.ANTIALIAS)
img.save(data, 'PNG', quality=JPEG_QUALITY)
data.seek(0)
return HttpResponse(
response = HttpResponse(
data,
content_type='image/png')
response['Cache-Control'] = 'max-age=%i' % CACHE_IMAGES_MAX_AGE
return response
if str(default) == 'pagan':
paganobj = pagan.Avatar(kwargs['digest'])
......@@ -181,9 +188,11 @@ class AvatarImageView(TemplateView):
img = paganobj.img.resize((size, size), Image.ANTIALIAS)
img.save(data, 'PNG', quality=JPEG_QUALITY)
data.seek(0)
return HttpResponse(
response = HttpResponse(
data,
content_type='image/png')
response['Cache-Control'] = 'max-age=%i' % CACHE_IMAGES_MAX_AGE
return response
if str(default) == 'identicon':
p = Pydenticon5()
......@@ -193,9 +202,11 @@ class AvatarImageView(TemplateView):
data = BytesIO()
img.save(data, 'PNG', quality=JPEG_QUALITY)
data.seek(0)
return HttpResponse(
response = HttpResponse(
data,
content_type='image/png')
response['Cache-Control'] = 'max-age=%i' % CACHE_IMAGES_MAX_AGE
return response
if str(default) == 'mm' or str(default) == 'mp':
# If mm is explicitly given, we need to catch that
......@@ -231,9 +242,11 @@ class AvatarImageView(TemplateView):
obj.save()
if imgformat == 'jpg':
imgformat = 'jpeg'
return HttpResponse(
response = HttpResponse(
data,
content_type='image/%s' % imgformat)
response['Cache-Control'] = 'max-age=%i' % CACHE_IMAGES_MAX_AGE
return response
class GravatarProxyView(View):
'''
......@@ -302,9 +315,11 @@ class GravatarProxyView(View):
data = BytesIO(gravatarimagedata.read())
img = Image.open(data)
data.seek(0)
return HttpResponse(
response = HttpResponse(
data.read(),
content_type='image/%s' % file_format(img.format))
response['Cache-Control'] = 'max-age=%i' % CACHE_IMAGES_MAX_AGE
return response
except ValueError as exc:
print('Value error: %s' % exc)
......
......@@ -30,6 +30,10 @@ If you've got a proposal to discuss or prefer to write to us, you can join our <
You can also put short notices to our attention on <a href="http://identi.ca/libravatar" title="http://identi.ca/libravatar">Identica<a/> or <a href="http://twitter.com/libravatar" title="http://twitter.com/libravatar">Twitter</a>.
<h4>Mastodon</h4>
Our Mastodon profile is available on <a href="https://photog.social/@libravatar">https://photog.social/@libravatar</a>.
<h4>Email</h4>
Finally, if you need to email us: <a href="mailto:dev@libravatar.org" title="mailto:dev@libravatar.org">dev@libravatar.org</a>
......
......@@ -71,6 +71,7 @@
<a class="btn btn-default" href="https://wiki.libravatar.org/">{% trans 'Wiki' %}</a><br/>
<a class="btn btn-default" href="http://blog.libravatar.org/">{% trans 'Blog' %}</a><br/>
<h3>{% trans 'Social media' %}</h3>
<a class="btn btn-default" rel="me" href="https://photog.social/@libravatar">Mastodon</a><br/>
<a class="btn btn-default" href="https://identi.ca/libravatar">Identica</a><br/>
<a class="btn btn-default" href="https://twitter.com/libravatar">Twitter</a><br/>
</section>
......