Compare commits

..

42 Commits

Author SHA1 Message Date
c64c4a1ba4 lol 2022-11-08 05:15:32 +11:00
c941397e7b good thing announces are still basic 2022-11-07 21:52:49 +11:00
0fb617976d Forgot to update the real css too 2022-09-15 14:41:11 +10:00
a724716d7e javashit 2022-09-14 18:39:35 +10:00
c3cfef4ae3 store dates 2022-09-13 04:52:58 +10:00
b7c4c1a207 Merge remote-tracking branch 'refs/remotes/origin/master' 2022-09-10 01:20:30 +10:00
00f15f1879 Did I forget to actually update this lol 2022-09-10 01:20:19 +10:00
ddae692f0b store update 2022-08-25 13:41:32 +10:00
20330437ea ... and date 2022-07-25 10:32:03 +10:00
83de5f58a2 articles update 2022-07-25 10:31:40 +10:00
e87f45bcd8 Added a bit more comment AND CREDITgit pushgit push 2022-05-31 00:59:57 +10:00
678204ec71 Fixed navbar being intrusive in lynx 2022-05-31 00:58:14 +10:00
743d6ec5ca Oh no I made a crash bug and it somehow got past adding an account on live but not on test 2022-05-28 23:25:59 +10:00
409ad95c05 Didn't forget to add this time. Thanks merge conflict, actually useful. 2022-05-27 03:49:34 +10:00
df9066e066 lol updated store info with whole section delete pending 2022-05-27 03:48:26 +10:00
17f3c5608e Hooboy changes. Store e stuff now has DB so I can put budget in (long overdue), plus make closed dates dynamic. Also added explanation of MD RSS, and some other things like pulling out dud nav entries. And... I think maybe navs have DB now too? IDK 2022-05-27 03:45:44 +10:00
9534763621 Announce 2022-05-05 09:46:34 +10:00
168bf85fe2 quick updatk 2022-04-15 13:18:55 +10:00
c293ba7bf7 Should update page date too even if it's just source code tweaks 2022-04-11 17:46:01 +10:00
67b7a5e20d Still bugging me 2022-04-11 17:39:12 +10:00
ec1858fd25 update store dates 2022-04-10 23:25:50 +10:00
ac76e69f4f That's been bugging me 2022-04-10 23:22:52 +10:00
2cd48b67ab I hit the name cap lol 2022-04-06 00:50:06 +10:00
0f1766ec94 cool article, also I can't recall which page I need to fix, there's one which shits all over the html 2022-04-06 00:45:02 +10:00
82f97cce0d ha... ha... One day I'll get good at testing 2022-03-27 20:19:48 +11:00
b4961d6213 I'm thinking of doing a module thing for the index page. 2022-03-27 02:59:32 +11:00
502fc62d1e store dates update 2022-03-22 20:21:37 +11:00
506b097929 lol 2022-03-13 19:29:06 +11:00
69a5889f55 shop link in navbar 2022-03-11 15:15:55 +11:00
6c567292e5 Redirects now use DB 2022-02-27 23:23:26 +11:00
f008d0030a test 2022-02-19 16:26:35 +11:00
6a2db02c4d Merge remote-tracking branch 'refs/remotes/origin/master' 2022-02-19 15:07:13 +11:00
31234c6e94 I need to automate that 2022-02-19 15:06:53 +11:00
419d5dfdc3 whoops 2022-02-15 17:46:13 +11:00
5c5015f418 Quick main page update 2022-02-15 17:43:25 +11:00
8562ea5e80 heh broke my site by forgetting to git add again 2022-02-10 19:16:28 +11:00
9b0d636299 Update date on homepage 2022-02-10 06:02:55 +11:00
5341583fb2 Sharing code is good. Also store page update (need to actually make store site proper already) 2022-02-09 19:59:04 +11:00
51661aaa71 lol, git 2022-01-27 20:59:32 +11:00
014b17e507 That page should go in the DB later 2022-01-27 16:40:56 +11:00
86421a7eb3 Finally put in proper converters, errors should be more accurate. Also put in an anti-slash redirect (because base only comes with pro-slash redirect, why...), and I think other stuff. 2022-01-26 19:51:03 +11:00
5e3fc17daa Oh, right, forgot to update this. 2022-01-13 14:03:46 +11:00
34 changed files with 417 additions and 152 deletions

3
.gitignore vendored
View File

@@ -61,6 +61,7 @@ cover/
local_settings.py
db.sqlite3
db.sqlite3-journal
migrations/
# Flask stuff:
instance/
@@ -138,4 +139,4 @@ dmypy.json
# Cython debug symbols
cython_debug/
rakka.conf
rakka.conf

6
books/converters.py Normal file
View File

@@ -0,0 +1,6 @@
class RealIntConverter:
regex='[0-9]+'
def to_python(self,value):
return int(value)
def to_url(self,value):
return str(value)

View File

@@ -1,8 +1,10 @@
from django.urls import path, re_path, include
from . import views
from django.urls import path, register_converter
from . import views,converters
register_converter(converters.RealIntConverter,'rint')
urlpatterns=[
path('',views.index,name='bidex'),
path('<str:bookurl>',views.book,name='bbook'),
path('<str:bookurl>/<str:chapnum>',views.chapter,name='bchap'),
path('<str:bookurl>/<rint:chapnum>',views.chapter,name='bchap'),
]

View File

@@ -1,46 +1,5 @@
from django.shortcuts import render
from . import models
from django.template import loader
import functools
def rerender(funky):
@functools.wraps(funky)
def wrap(req,*args,**kwargs):
with open('main/utils/navs') as b:
navs=parsecat(b,4)
namednavs=[{'id':blah[0], 'link':blah[1], 'text':blah[2], 'align':int(blah[3])} for blah in navs['']]
out=funky(*args,**kwargs)
temp=loader.get_template('main/nav.html')
out['nav']=temp.render({"navs":namednavs},None)
return render(req, 'main/temp.html', out)
return wrap
def parsecat(file,n):
if not isinstance(file,str):
# Assume open handle
stuff=file.read()
else:
with open(f'main/pages/{file}') as b:
stuff=b.read()
cats=stuff.split('\n\n')
out={}
head=''
out['']=[]
for cat in cats:
if ':' in cat[:cat.index('\n')]:
# We have a category name
head,cat=cat.split('\n',1)
head=head[:-1]
out[head]=[]
else: head=''
for line in cat.split('\n'):
lin=line.split(',',n-1)
pad=n-len(lin)
lin.extend(['']*pad)
out[head].append(lin)
if out['']==[]: del(out[''])
return out
from rakka.utils import rerender
@rerender
def index():
@@ -58,6 +17,6 @@ def book(bookurl):
@rerender
def chapter(bookurl,chapnum):
book=models.Book.objects.filter(url=bookurl)[0]
chapter=models.Chapter.objects.filter(book=book,number=int(chapnum))[0]
chapter=models.Chapter.objects.filter(book=book,number=chapnum)[0]
text='<p>'+chapter.contents.replace('<','&lt;').replace('>','&gt;').replace('\n\n','</p><p>').replace('\n','<br/>')+'</p>'
return {'title':chapter,'content':'<p>Navigation buttons will come later...</p>\n'+text,'date':chapter.added}

0
comment/__init__.py Normal file
View File

3
comment/admin.py Normal file
View File

@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
comment/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class CommentConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'comment'

View File

3
comment/models.py Normal file
View File

@@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

3
comment/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

7
comment/urls.py Normal file
View File

@@ -0,0 +1,7 @@
from django.urls import include, path
from . import views
urlpatterns=[
path('',views.look,name='look'),
path('new',views.submit,name='new'),
]

11
comment/views.py Normal file
View File

@@ -0,0 +1,11 @@
from django.shortcuts import render
from rakka.utils import rerender
# Create your views here.
@rerender
def look():
pass
@rerender
def submit():
pass

View File

@@ -2,7 +2,8 @@ from django.contrib import admin
# Register your models here.
from .models import Page,Contact,Update
from .models import Page,Contact,Update,Redirect
admin.site.register(Page)
admin.site.register(Contact)
admin.site.register(Update)
admin.site.register(Update)
admin.site.register(Redirect)

23
main/converters.py Normal file
View File

@@ -0,0 +1,23 @@
from .models import Page,Redirect
class AutoPageConverter:
regex='.*'
def to_python(self,value):
try: p=Page.objects.get(url=value)
except Page.DoesNotExist: raise ValueError(f'No such page {value}')
if not p: raise ValueError(f'No such page {value}')
return p
def to_url(self,value):
if not isinstance(value,Page): raise ValueError('Given value is not a Page')
return p.url
class RedirectConverter:
regex='.*'
def to_python(self,value):
try: r=Redirect.objects.get(match=value)
except Redirect.DoesNotExist: raise ValueError(f'No such redirect {value}')
if not r: raise ValueError(f'No such redirect {value}')
return r
def to_url(self,value):
if not isinstance(value,Redirect): raise ValueError('Given value is not a Redirect')
return p.match

View File

@@ -1,5 +1,6 @@
from django.db import models
from datetime import date
from django.utils.timezone import now
# Create your models here.
@@ -23,6 +24,7 @@ class Contact(models.Model):
priority=models.IntegerField()
desktop=models.BooleanField(default=True)
mobile=models.BooleanField(default=True)
rel=models.BooleanField(default=False)
def save(self,*args,**kwargs):
a,_=Update.objects.get_or_create(page='contact')
@@ -35,8 +37,11 @@ class Contact(models.Model):
class Update(models.Model):
page=models.CharField(max_length=100)
date=models.DateField()
date=models.DateField(default=now)
class Redirect(models.Model):
match=models.CharField(max_length=200)
output=models.CharField(max_length=500)
output=models.CharField(max_length=500)
def __str__(self):
return self.match

View File

@@ -1,24 +1,34 @@
Nettiquette and misc:
Nettiquette:
http://www.nohello.com
https://nohello.net/
https://sol.gfxile.net/dontask.html
https://dontasktoask.com/
http://slash7.com/2006/12/22/vampires/
http://xyproblem.info/
Politicking:
https://ncase.me/ballot
https://digdeeper.neocities.org/ghost/email.html
http://www.kanjidamage.com
https://innermantheatre.com/2021/03/29/lightspeed-lab-homosexuality/,The Christian stance on homosexuality in 3 panels
Economics:
https://archive.secondspring.co.uk/articles/borruso.htm
Computers and languages are hard:
http://www.zompist.com/yingzi/yingzi.htm
Computers are hard:
https://gankra.github.io/blah/text-hates-you/
https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/
https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time
https://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time
https://eev.ee/blog/2015/09/12/dark-corners-of-unicode/
http://michael.orlitzky.com/articles/motherfuckers_need_package_management.xhtml
https://idlewords.com/talks/website_obesity.htm
https://digdeeper.club/articles/email.xhtml
https://spyware.neocities.org/articles/brave.html,Computers are your enemy
https://prose.sh/
Languages are hard:
http://www.zompist.com/yingzi/yingzi.htm
http://www.kanjidamage.com,The right way to learn kanji
https://faculty.georgetown.edu/jod/texts/twain.german.html,Languages are angry
Otome! And maybe other game design:
https://uguucageoflove.wordpress.com/2020/05/17/preferences-of-otome-gamers-a-survey-of-japanese-players/
https://uguucageoflove.wordpress.com/2020/05/17/preferences-of-otome-gamers-a-survey-of-japanese-players/

View File

@@ -1,10 +1,20 @@
<audio controls><source src='https://invidious.ethibox.fr/latest_version?id={0}&itag=140'/>ababababa</audio>
<p>Rakka me takkas and riddly me diddlies.</p>
<p>Welcome back, Ike. Farewell, Sly.</p><br/>
<p>This site is hosted in Tasmania, AU, by zerglingman (a fedora.email user), a Van Canto fan<del>girl</del> boy. Also available on matrix as @zergling.man:matrix.perthchat.org, or on libera.chat as Zergling_man or Mastodon as <a rel='me' href='https://mastodon.linuxbox.ninja/@Zergling_man'>@Zergling_man@mastodon.linuxbox.ninja</a> (<a href='/contact.php'>and many other places</a>). <br/><a href='/me'>But who am I, really?</a></p>
<p>Who <del>can't figure out how SSL works. I'm working on it. got SSL working, I guess.</del> is figuring this SSL thing out, properly.</p>
<p><a href='/webhost.php'>Haha I'm way too lazy for webhosting</a></p>
<p>This site is hosted in Tasmania, AU, by zerglingman (a fedora.email user), a Van Canto fan<del>girl</del> boy. Also available on matrix as <a href="https://matrix.to/#/@zergling.man:perthchat.org">@zergling.man:perthchat.org</a>, or on libera.chat as Zergling_man or fedi (inc. mastodon) as <a rel='me' href='https://birds.garden/@Zergling_man'>@Zergling_man@birds.garden</a> (<a href='/contact'>and many other places</a>). <br/><a href='/me'>But who am I, really?</a></p>
<p>Who <del>can't figure out how SSL works. I'm working on it. got SSL working, I guess. is figuring this SSL thing out, properly.</del> is thinking about eliminating CAs.</p>
<p><a href='/webhost'>Haha I'm way too lazy for webhosting</a></p>
<p>Cool games: <a href='http://www.fantasystrike.com'>Fantasy Strike</a> (<strong>gone free! Go play it now!</strong>), <a href='http://www.soldak.com/Dins-Curse/Overview.html'>Din's Curse</a> (dirt cheap!), <a href='https://mwomercs.com/'>Mechwarrior Online</a> (free!), <a href='https://www.wurmonline.com/'>Wurm Online</a> (free!), <a href='https://www.chiark.greenend.org.uk/~sgtatham/puzzles/'>Portable Puzzle Collection</a> (free and open source! Also on <a href='https://f-droid.org/en/packages/name.boyle.chris.sgtpuzzles/'>android</a>!)</p>
<p>Cool bands: <a href='https://vancanto.de/en'>Van Canto</a> [<a href='https://vancanto.bandcamp.com/'>bandcamp</a>] (Who this site is a shrine to!), <a href='https://theocracymusic.com/'>Theocracy</a> [<a href='https://ulteriumrecords.bandcamp.com/'>label's bandcamp</a>] (Christian prog metal!), <a href='https://teramaze.com.au/'>Teramaze</a> [<a href='https://teramaze.bandcamp.com/'>bandcamp</a>] (Australian Christian prog metal! Always releasing!), Takamachi Walk [<a href='https://takamachiwalk.bandcamp.com/'>bandcamp</a>] (Touhou metal! New album out NYE 2021!)
<p><del><a href='https://www.bigr.com/whisker-snot-arrow-rest-weatherproofing/208374.html'>Wisknort. Whisker snot.</a></del> They changed their website and now it sucks.</p>
<p>By the way, my site's now <a href='https://gitea.rakka.tk/Zergling_man/rakkapy'>open source</a>, so you can see exactly how shit I am at this.</p>
<p>By the way, my site's now <a href='https://gitea.rakka.tk/Zergling_man/rakkapy'>open source</a>, so you can see exactly how shit I am at this.</p>
<h4>Notices:</h4>
<ul>
<li>2022 Nov 8th: False alarm, I just needed to restart the DB.</li>
<li>2022 Nov 7th: Database access is fucked, I don't know why, but large parts of my site will be inaccessible as a result (including, annoyingly, the contact page). I will probably redo the whole thing as a static site instead of trying to fix it.</li>
<li>2022 Apr 5th: I think I've figured out what was causing constant dropouts, uptime should be back to &gt;99%.</li>
<li>2022 Mar 27th: Oh yeah I found those other things. One is now at <a href="https://rakka.tk/r/support">https://rakka.tk/r/support</a>, the other is <a href="https://bae.st/media/38f1485d-a6bd-4b30-a409-0d9e75f22d19/bf313a3566fc2ada.png">here</a></li>
<li>2022 Feb 15th: Here are some links for a certain person I was speaking to. Actually a couple of people. <a href='https://mangadex.org/manga/c6a51a13-74fd-46bd-989e-5cdaa26542f6'>Hero BBS</a>, parodying isekai before isekai was big. I still haven't found the other things I mentioned.</li>
<li>2022 Feb 9th: Someone discovered that my ftp server was externally accessible and allowed anonymous writes and edits. Unfortunately I am too incompetent to have had it logging properly so I didn't get their IP, sad! Still, I feel special. Now I know I've made it.</li>
</ul>

View File

@@ -1,20 +0,0 @@
adobe: https://www.patreon.com/posts/26834357
faplog: https://docs.google.com/spreadsheets/d/1sIh5evj1Janf_fdefbrksGLyHO_uMMDOjHJReA0P0fw/edit
fpdam: https://docs.google.com/document/d/1XSKSC9PYxAE1ys2u5ALD3wDBaps6LQgGe-GtyAju3q8/edit?usp=sharing
fpdb: https://docs.google.com/spreadsheets/d/1iJd8dBMbAKfwbfcWNnE-tElu4amJdtz4iMxWCxwKNY8/edit
fuckmeyourself: https://gelbooru.com/index.php?page=post&s=view&id=4608040
hitspark: https://images.squarespace-cdn.com/content/v1/5728734545bf2166bba67b00/1538785588130-I8WVGV947EEW81LII25S/ke17ZwdGBToddI8pDm48kODKEPcE7oOaZ-HX_UAJexAUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dhV8WLpqAVTw2_ZfbaHHLLR7LAwPhjFlJ4O4wogcebl8m7cT0R_dexc_UL_zbpz6JQ/frame_advantage_5up.jpg?format=1000w
homo: https://innermantheatre.files.wordpress.com/2020/11/lightspeed-lab-ep.261-homosexuality.jpg
homo/s: https://innermantheatre.com/2021/03/29/lightspeed-lab-homosexuality/
nadeko: https://docs.google.com/spreadsheets/d/12ZpOI3coZHlSFQ7oFuo1HzbkTkgX8RBk06oeMM56HFQ/edit#gid=0
nlship: https://docs.google.com/document/d/1oVZSv7v8cePVu22qmbgkCUtm9LnUcSZIaQyH-3b_DhI/edit?usp=sharing
nlvn: https://docs.google.com/document/d/1tVVI2NAY_1vFLsMrbRzn18FiXNzZcDgdxnNXKHEFzTs/edit#
osscans: https://discord.gg/VStXkfm
ossd: https://drive.google.com/drive/folders/14xIZJER551zEB9rP9d655MdpRE0xDBW8
perm: http://nadekobot.readthedocs.io/en/latest/Permissions%20System/
rinbot: https://discordapp.com/oauth2/authorize?client_id=448458599673364481&scope=bot
sauce: https://discord.gg/gsUT8B
spook: https://rakka.tk/pics/SPOOKY/SCARY/SKELETONS/SEND/SHIVERS/DOWN/YOUR/SPINE/SHRIEKING/SKULLS/WILL/SHOCK/YOUR/SOUL/SEAL/YOUR/DOOM/TONIGHT/SPOOKY/SCARY/SKELETONS/SPEAK/WITH/SUCH/A/SCREECH/YOU'LL/SHAKE/AND/SHUDDER/IN/SURPRISE/WHEN/YOU/HEAR/THESE/ZOMBIES/SHRIEK/WE'RE/SO/SORRY/SKELETONS/YOU'RE/SO/MISUNDERSTOOD/YOU/ONLY/WANT/TO/SOCIALIZE/BUT/I/DON'T/THINK/WE/SHOULD/CAUSE_SPOOKY_SCARY_SKELETONS_SHOUT_STARTLING_SHRILLY_SCREAMS.gif
wou: https://discord.gg/8sc5m6R
WushuAT: https://docs.google.com/document/d/1wtJ6JCpmpr-ziAb0UR0OpW1tX7Ms5CiDFUQkjPgFzIE/edit?usp=drive_web&ouid=102857329945830311247
years: https://docs.google.com/spreadsheets/d/1p7NIoC2-o8BJvbLD5N1WazaFAtw4vto7bxJMGsarcgE/edit

View File

@@ -5,12 +5,25 @@
<title>
Tas [] & Van Canto - {{ title }}
</title>
<script type="text/javascript">
function b(){
a=document.body.innerHTML
document.body.innerHTML = '<main><p>Please disable JavaScript to view this site.</p><p><a href="/javashit">Why?</a> <a href="https://www.wikihow.com/Disable-JavaScript">How?</a></p><p id="tock" class="tick">Or wait <n id="tick">3</n> seconds...</p></main>'
function t1(){document.getElementById('tick').textContent=2}
function t2(){document.getElementById('tick').textContent=1}
function c(){console.log("fucking normie"); document.body.innerHTML=a}
window.setTimeout(t1,1000)
window.setTimeout(t2,2000)
window.setTimeout(c,3000)
}
</script><!--Need to add a timer to remove it first. I'm not *that* mean. Credit: https://soc.punktrash.club/objects/bfe4fc29-96d5-4f90-9f9e-4092e7c273a4-->
</head>
<body>
{{ nav }}
<body onload=b()>
<!--Move navbar to the bottom and use flex to reorder it to the top, so it isn't as intrusive without CSS.-->
<main>
{% autoescape off %}{{ content }}{% endautoescape %}
</main>
<p class="foot">Page last updated {{ date }}</p>
{{ nav }}
</body>
</html>

View File

@@ -1,5 +1,8 @@
from django.urls import path, re_path, include
from . import views
from django.urls import path, register_converter
from . import views,converters
register_converter(converters.AutoPageConverter,'autopage')
register_converter(converters.RedirectConverter,'redirect')
urlpatterns=[
path('',views.index,name='idex'),
@@ -7,11 +10,10 @@ urlpatterns=[
path('comment',views.comment,name='shoutbox'),
path('specs',views.specs,name='specs'),
path('songs',views.songs,name='songs'),
path('nerdshope',views.nerdshope,name='shop'),
path('teapot',views.teapot,name='teapot'),
path('toask',views.articles,name='articles'),
re_path('r/(.*)',views.redirect,name='redirect'),
path('r/<redirect:src>',views.redirect,name='redirect'),
path('md.rss',views.md,name='md'),
path('me.vcf',views.vcard,name='vcard'),
re_path('(.*)',views.autopage,name='everything'),
path('<autopage:page>',views.autopage,name='everything'),
]

View File

@@ -4,9 +4,10 @@ syntax,/syntax,Syntaxer,2
todo,/todos,Todos,0
pics,/pics,Pics,2
wargame,https://gitlab.com/zergling-man/Wargamer,Wargamer,0
rinbot,/r/rinbot,Rinbot,0
rinbot,/r/rinbot,Rinbot,2
survey,/emojisurvey.php,Survey,2
myroids,/myroids,Myroids,0
bot,/bot,Bot chat,2
articles,/toask,Articles,0
contact,/contact,Contact,1
contact,/contact,Contact,1
shope,/nerdshope,Nerds' Hope,0

View File

@@ -1,50 +1,10 @@
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
import random as ra
import asyncio
from . import mdl
from .models import Page,Contact,Update
from .models import Page,Contact,Update,Redirect
import functools
def rerender(funky):
@functools.wraps(funky)
def wrap(req,*args,**kwargs):
with open('main/utils/navs') as b:
navs=parsecat(b,4)
namednavs=[{'id':blah[0], 'link':blah[1], 'text':blah[2], 'align':int(blah[3])} for blah in navs['']]
out=funky(*args,**kwargs)
temp=loader.get_template('main/nav.html')
out['nav']=temp.render({"navs":namednavs},None)
return render(req, 'main/temp.html', out)
return wrap
def parsecat(file,n):
if not isinstance(file,str):
# Assume open handle
stuff=file.read()
else:
with open(f'main/pages/{file}') as b:
stuff=b.read()
cats=stuff.split('\n\n')
out={}
head=''
out['']=[]
for cat in cats:
if ':' in cat[:cat.index('\n')]:
# We have a category name
head,cat=cat.split('\n',1)
head=head[:-1]
out[head]=[]
else: head=''
for line in cat.split('\n'):
lin=line.split(',',n-1)
pad=n-len(lin)
lin.extend(['']*pad)
out[head].append(lin)
if out['']==[]: del(out[''])
return out
from rakka.utils import rerender,parsecat
@rerender
def index():
@@ -54,11 +14,12 @@ def index():
raws=b.read()
ids=raws.split('\n')
stuff=stuff.format(ra.choice(ids))
return {'title':'Home','content':stuff,'date':'2021/12/15'}
return {'title':'Home','content':stuff,'date':'2022/02/09'}
def lii(obj):
def lii(obj): # This will get moved to a template shortly
name=obj.name
if obj.url: name=f"<a href='{obj.url}'>{name}</a>"
relme="rel='me' " if obj.rel else ''
if obj.url: name=f"<a {relme}href='{obj.url}'>{name}</a>"
if obj.comment: name=f"{name} ({obj.comment})"
if obj.desktop: name=f"{name} 🖥"
if obj.mobile: name=f"{name} 📱"
@@ -79,7 +40,7 @@ def contact():
out2+='\n'.join(map(lii,v))
out2+="\n</ul></p>"
out3+=out2
return {'title':'Contact','content':head+out3,'date':Update.objects.get(page='contact').date}
return {'title':'Contact','content':head+out3,'date':Update.objects.get_or_create(page='contact')[0].date}
def specs(req):
with open('main/pages/specs') as b:
@@ -97,10 +58,6 @@ def songs():
out='This is the full list of songs that can appear on the home page.<br/>'+'<br/>\n'.join([f'<a href="https://invidious.ethibox.fr/watch?v={idd}">https://invidious.ethibox.fr/watch?v={idd}</a>' for idd in ids])
return {'title':'Songs','content':out,'date':'2021/05/06'}
@rerender
def nerdshope():
return {'title':'Nerds\' Hope','content':"Store stuff. TODO. Will include inventory and budget. <a href='https://facebook.com/nerdshope'>FB</a><br/>Address is 21 Kensington St, Glenorchy<br/>Off dates 2022:Dunno yet.<br/>NYE party 31st Dec.",'date':'2021/12/24'}
def teapot(req):
return HttpResponse("You're probably missing the joke.",status=418)
@@ -110,18 +67,21 @@ def articles():
arts=parsecat('articles',2)
out=[]
for k,v in arts.items():
out.append(f'<h4>{k}</h4>'+ '<br/>'.join([f'<a href="{l[0]}">{l[1] or l[0]}</a>' for l in v]))
return {'title':'Articles','content':'<p>'+('</p><p>'.join(out))+'</p>','date':'2021/05/06'}
out.append(f'<h4>{k}</h4>\n'+ '<br/>\n'.join([f'<a href="{l[0]}">{l[1] or l[0]}</a>' for l in v]))
return {'title':'Articles','content':'<p>'+('</p>\n<p>'.join(out))+'</p>','date':'2022/07/25'}
def redirect(req,src):
with open('main/pages/redirects') as b:
lonks=b.read()
lonks=dict([n.split(': ',1) for n in lonks.split('\n')])
return HttpResponse(status=302,headers={'Location':lonks[src]})
return HttpResponse(status=302,headers={'Location':src.output})
@rerender
def mdhelp():
return {'title':'How2MD RSS','date':'2022/05/27','content':"This is an <a href='https://en.wikipedia.org/wiki/RSS'>RSS</a> service for <a href='https://mangadex.org'>Mangadex</a>, since they had one in v3 that I made liberal use of, and I've heard nothing regarding its return in v5.<br/>If you've never used RSS before, I strongly recommend starting, as it's the second-best update notification system in existence (and it could be built on #1, push notifications, but that's an another topic).<br/>You will need an RSS reader program, but your browser probably has one built in, so you can just use that. (I don't recommend it, because you should be closing the browser more, not less.)<br/>The important part of an RSS feed is a source URL. If properly configured, that should provide everything else. In this case, you've already found the source URL... Kinda. You need to pass a manga ID (or several) to make it work. A manga ID looks like this: ed996855-70de-449f-bba2-e8e24224c14d (yes, that's a UUID4). If you go to a manga's page on Mangadex, you should see something like it in the URL bar at the top. I think Tachiyomi has some way to grab it, but I also think Tachi's update notifs are better than mine, so if you have that you don't need this.<br/>Once you have the ID(s), you should palm them into this page like this: <a href='/md.rss?ids=ed996855-70de-449f-bba2-e8e24224c14d'>https://rakka.tk/md.rss?ids=ed996855-70de-449f-bba2-e8e24224c14d</a>. Take that and give it to your RSS reader as a new feed and it should handle the rest (did your browser ask you a new question when you clicked it?). If you want more IDs, put an & and do it again: <a href='/md.rss?ids=ed996855-70de-449f-bba2-e8e24224c14d&ids=/d032cdeb-1ced-4031-8b9e-45e6064c1781'>https://rakka.tk/md.rss?ids=ed996855-70de-449f-bba2-e8e24224c14d&ids=d032cdeb-1ced-4031-8b9e-45e6064c1781</a>.<br/>It behaves a bit differently with 1 ID vs multiple, but it should work alright both ways. Personally I prefer making one feed for each series."}
def md(req):
ids=req.GET.getlist('ids','')
if not ids: return mdhelp(req)
loop=asyncio.get_event_loop()
feed=loop.run_until_complete(mdl.makefeed(req.GET.getlist('ids','')))
feed=loop.run_until_complete(mdl.makefeed(ids))
return HttpResponse(feed, content_type='application/rss+xml')
def vcard(req):
@@ -139,5 +99,4 @@ END:VCARD""")
@rerender
def autopage(page):
p=Page.objects.get(url=page)
return {'title':p.title,'content':p.contents,'date':p.last_edited}
return {'title':page.title,'content':page.contents,'date':page.last_edited}

0
nerdshope/__init__.py Normal file
View File

8
nerdshope/admin.py Normal file
View File

@@ -0,0 +1,8 @@
from django.contrib import admin
# Register your models here.
from .models import BankAccount,Payment,OffDate
admin.site.register(BankAccount)
admin.site.register(Payment)
admin.site.register(OffDate)

6
nerdshope/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class NerdshopeConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'nerdshope'

30
nerdshope/models.py Normal file
View File

@@ -0,0 +1,30 @@
from django.db import models
from django.utils.timezone import now
# Create your models here.
class BankAccount(models.Model):
name=models.CharField(max_length=100)
physical=models.CharField(max_length=100)
currency=models.CharField(max_length=5)
@property
def balance(self): return sum(map(lambda x:x.amount,Payment.objects.filter(account=self)))
def __str__(self):
return str(self.name)+', '+str(self.balance)
class Payment(models.Model):
timestamp=models.DateTimeField(default=now)
other_party=models.CharField(max_length=100)
account=models.ForeignKey(BankAccount, on_delete=models.CASCADE)
amount=models.IntegerField(default=0)
reason=models.CharField(max_length=200)
def __str__(self):
return str(self.timestamp)+', '+str(self.amount)+', '+str(self.reason)
class OffDate(models.Model):
when=models.DateField(default=now)
reason=models.CharField(max_length=50,default="Hall unavailable")
def __str__(self):
return str(str.when)+': '+str(self.reason)

3
nerdshope/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

6
nerdshope/urls.py Normal file
View File

@@ -0,0 +1,6 @@
from django.urls import include, path
from . import views
urlpatterns = [
path('',views.nerdshope,name='shop'),
]

16
nerdshope/views.py Normal file
View File

@@ -0,0 +1,16 @@
from django.shortcuts import render
from rakka.utils import rerender
from . import models
from main.models import Update
@rerender
def nerdshope():
accounts=models.BankAccount.objects.all()
sums={curr:sum([n.balance for n in filter(lambda x:x.currency==curr,accounts)]) for curr in set(map(lambda x:x.currency,accounts))}
moneyblob='</li>\n<li>'.join([f'{k}: {v}' for k,v in sums.items()])
moneyblob='Current monetary state: <ul>\n<li>'+moneyblob+'</li>\n</ul>'
return {'title':"Nerds' Hope",'content':"Store stuff. TODOing. Will include inventory and budget. <a href='https://facebook.com/nerdshope'>FB</a><br/>\nAddress is 21 Kensington St, Glenorchy<br/>\nThe store isn't open when other events happen on Fridays, usually the last Friday of each month. Additionally, on the first and third weeks of each month the store will move around the back (through the gate) around 18:00 to make room for a youth group. If in doubt, ask the youth group for directions.<br/>\nFull list of dates:\n<ol><li>16th Sept - round the back later</li>\n<li>30th Sept - closed</li>\n<li>21st Oct - round the back later</li>\n<li>28th Oct - closed</li>\n<li>4th Nov - round the back later</li>\n<li>18th Nov - round the back later</li>\n<li>25th Nov - closed</li>\n<li>2nd Dec - round the back later</li>\n<li>16th Dec - round the back later</li>\n<li>30th Dec - maybe party</li></ol>\n"+moneyblob,'date':Update.objects.get_or_create(page='nh_main')[0].date}
@rerender
def budget():
pass

133
rakka/UncommonMiddleware.py Normal file
View File

@@ -0,0 +1,133 @@
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.http import HttpResponsePermanentRedirect
from django.urls import is_valid_path
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import escape_leading_slashes
class UnCommonMiddleware(MiddlewareMixin):
"""
Lol, common
"""
response_redirect_class = HttpResponsePermanentRedirect
def process_request(self, request):
"""
Check for denied User-Agents and rewrite the URL based on
settings.APPEND_SLASH and settings.PREPEND_WWW
"""
# Check for denied User-Agents
user_agent = request.META.get('HTTP_USER_AGENT')
if user_agent is not None:
for user_agent_regex in settings.DISALLOWED_USER_AGENTS:
if user_agent_regex.search(user_agent):
raise PermissionDenied('Forbidden user agent')
# Check for a redirect based on settings.PREPEND_WWW
host = request.get_host()
must_prepend = settings.PREPEND_WWW and host and not host.startswith('www.')
redirect_url = ('%s://www.%s' % (request.scheme, host)) if must_prepend else ''
# Check if a slash should be appended or removed
if self.should_redirect_with_slash(request):
path = self.get_full_path_with_slash(request)
elif self.should_redirect_without_slash(request):
path = self.get_full_path_without_slash(request)
else:
path = request.get_full_path()
# Return a redirect if necessary
if redirect_url or path != request.get_full_path():
redirect_url += path
return self.response_redirect_class(redirect_url)
def should_redirect_with_slash(self, request):
"""
Return True if settings.APPEND_SLASH is True and appending a slash to
the request path turns an invalid path into a valid one.
"""
if settings.APPEND_SLASH and not request.path_info.endswith('/'):
urlconf = getattr(request, 'urlconf', None)
if not is_valid_path(request.path_info, urlconf):
match = is_valid_path('%s/' % request.path_info, urlconf)
if match:
view = match.func
return getattr(view, 'should_append_slash', True)
return False
def get_full_path_with_slash(self, request):
"""
Return the full path of the request with a trailing slash appended.
Raise a RuntimeError if settings.DEBUG is True and request.method is
POST, PUT, or PATCH.
"""
new_path = request.get_full_path(force_append_slash=True)
# Prevent construction of scheme relative urls.
new_path = escape_leading_slashes(new_path)
if settings.DEBUG and request.method in ('POST', 'PUT', 'PATCH'):
raise RuntimeError(
"You called this URL via %(method)s, but the URL doesn't end "
"in a slash and you have APPEND_SLASH set. Django can't "
"redirect to the slash URL while maintaining %(method)s data. "
"Change your form to point to %(url)s (note the trailing "
"slash), or set APPEND_SLASH=False in your Django settings." % {
'method': request.method,
'url': request.get_host() + new_path,
}
)
return new_path
def should_redirect_without_slash(self, request):
"""
Removing slashes, of course
"""
if settings.REMOVE_SLASH and request.path_info.endswith('/'):
urlconf = getattr(request, 'urlconf', None)
if not is_valid_path(request.path_info, urlconf):
match = is_valid_path('%s' % request.path_info[:-1], urlconf)
if match:
view = match.func
return getattr(view, 'should_remove_slash', True)
return False
def get_full_path_without_slash(self, request):
"""
z
"""
new_path = request.get_full_path(force_append_slash=True)[:-1]
# Prevent construction of scheme relative urls.
new_path = escape_leading_slashes(new_path)
if settings.DEBUG and request.method in ('POST', 'PUT', 'PATCH'):
raise RuntimeError(
"You called this URL via %(method)s, but the URL doesn't end "
"in a slash and you have APPEND_SLASH set. Django can't "
"redirect to the slash URL while maintaining %(method)s data. "
"Change your form to point to %(url)s (note the trailing "
"slash), or set APPEND_SLASH=False in your Django settings." % {
'method': request.method,
'url': request.get_host() + new_path,
}
)
return new_path
def process_response(self, request, response):
"""
When the status code of the response is 404, it may redirect to a path
with an appended slash if should_redirect_with_slash() returns True.
"""
# If the given URL is "Not Found", then check if we should redirect to
# a path with a slash appended.
if response.status_code == 404 and self.should_redirect_with_slash(request):
return self.response_redirect_class(self.get_full_path_with_slash(request))
if response.status_code == 404 and self.should_redirect_without_slash(request):
return self.response_redirect_class(self.get_full_path_without_slash(request))
# Add the Content-Length header to non-streaming responses if not
# already set.
if not response.streaming and not response.has_header('Content-Length'):
response.headers['Content-Length'] = str(len(response.content))
return response

View File

@@ -35,6 +35,7 @@ ALLOWED_HOSTS = [n.strip() for n in conf['ALLOWED_HOSTS'].split(',')]
INSTALLED_APPS = [
'main.apps.MainConfig',
'books.apps.BooksConfig',
'nerdshope.apps.NerdshopeConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
@@ -46,7 +47,7 @@ INSTALLED_APPS = [
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'rakka.UncommonMiddleware.UnCommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
@@ -104,6 +105,7 @@ AUTH_PASSWORD_VALIDATORS = [
},
]
REMOVE_SLASH=True
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/

View File

@@ -20,5 +20,7 @@ from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('books/',include('books.urls')),
path('comment/',include('comment.urls')),
path('nerdshope/',include('nerdshope.urls')),
path('', include('main.urls')),
]

41
rakka/utils.py Normal file
View File

@@ -0,0 +1,41 @@
from django.shortcuts import render
from django.template import loader
import functools
def rerender(funky):
@functools.wraps(funky)
def wrap(req,*args,**kwargs):
with open('main/utils/navs') as b:
navs=parsecat(b,4)
namednavs=[{'id':blah[0], 'link':blah[1], 'text':blah[2], 'align':int(blah[3])} for blah in navs['']]
out=funky(*args,**kwargs)
temp=loader.get_template('main/nav.html')
out['nav']=temp.render({"navs":namednavs},None)
return render(req, 'main/temp.html', out)
return wrap
def parsecat(file,n):
if not isinstance(file,str):
# Assume open handle
stuff=file.read()
else:
with open(f'main/pages/{file}') as b:
stuff=b.read()
cats=stuff.split('\n\n')
out={}
head=''
out['']=[]
for cat in cats:
if ':' in cat[:cat.index('\n')]:
# We have a category name
head,cat=cat.split('\n',1)
head=head[:-1]
out[head]=[]
else: head=''
for line in cat.split('\n'):
lin=line.split(',',n-1)
pad=n-len(lin)
lin.extend(['']*pad)
out[head].append(lin)
if out['']==[]: del(out[''])
return out

View File

@@ -5,6 +5,11 @@ body
margin: 0px;
padding: 0px;
/*Move navbar to the bottom and use flex to reorder it to the top, so it isn't as intrusive without CSS.
Thanks to @heftig:archlinux.org (matrix) for showing me this.*/
display: flex;
flex-direction: column;
}
nav
@@ -21,6 +26,7 @@ nav
display: inline-block;
background-color: #9999ff;
order: 1; /*flex thing*/
}
main
@@ -41,6 +47,7 @@ main
margin-right: auto;
border: 2px solid;
text-align: center;
order: 2; /*flex thing*/
}
main *
@@ -64,7 +71,7 @@ li.navpiece
position:relative;
}
a.navpiece, div.navpiece
a.navpiece/*, div.navpiece Apparently this wasn't doing anything either.*/
{
text-decoration-line:none;
display: table-cell;
@@ -123,7 +130,13 @@ h1
background-color: #cccccc;
float: right;
margin-left: auto;
margin-right: auto;
margin-right: 0; /* Need to set this for flex thing*/
border: 2px solid;
text-align: center;
order: 3; /*flex thing*/
}
.tick
{
color: #dddddd;
}