Skip to content

Commit

Permalink
[update]
Browse files Browse the repository at this point in the history
  • Loading branch information
boke0 committed Mar 7, 2021
0 parents commit 5af8be8
Show file tree
Hide file tree
Showing 122 changed files with 11,836 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kyokusui/__pycache__/
7 changes: 7 additions & 0 deletions kyokusui/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from mitama.app import Builder

from .main import App


class AppBuilder(Builder):
app = App
198 changes: 198 additions & 0 deletions kyokusui/controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
from mitama.app import Controller
from mitama.app.http import Response
from mitama.models import User, Node, Role, is_admin
from datetime import datetime
import json
import re
import markdown
import magic

from .model import db, Board, Thread, Res, Permission
from .forms import CreateBoardForm, CreateThreadForm, SettingForm
from .utils import hiroyuki

class HomeController(Controller):
def handle(self, request):
template = self.view.get_template("home.html")
threads = list()
for board in Board.list_subscribed(request.user):
for thread in board.threads:
if not thread.closed:
threads.append(thread)
return Response.render(template, {
"is_admin": is_admin,
"threads": threads,
"boards": Board.list_subscribed(request.user)
})
def settings(self, request):
template = self.view.get_template("settings.html")
error = ""
if request.method == "POST":
form = SettingForm(request.post())
for permission_screen_name, permission_roles in form['permissions'].items():
permission = Permission.retrieve(screen_name = permission_screen_name)
permission.roles = [Role.retrieve(screen_name = r) for r in permission_roles]
permission.update()
error = "保存しました"
return Response.render(template, {
"permissions": Permission.list(),
"roles": Role.list(),
"error": error
})

class BoardController(Controller):
def create(self, request):
form = CreateBoardForm(request.post())
board = Board()
board.name = form['name']
board.owner = Node.retrieve(form['owner'])
board.create()
return Response.json({
"_id": board._id,
})

def retrieve(self, request):
template = self.view.get_template("board.html")
board = Board.retrieve(request.params['board'])
return Response.render(template, {
"board": board,
"boards": Board.list_subscribed(request.user)
})

def subscribe(self, request):
board = Board.retrieve(request.params['board'])
board.subscribers.append(request.user)
board.update()
return Response.json({
"subscribe": True,
"board": {
"_id": board._id
}
})

def unsubscribe(self, request):
board = Board.retrieve(request.params['board'])
board.subscribers.remove(request.user)
board.update()
return Response.json({
"subscribe": False,
"board": {
"_id": board._id
}
})

class UserController(Controller):
def icon(self, request):
user = User.retrieve(request.params['user'])
f = magic.Magic(mime=True, uncompress=True)
mime = f.from_buffer(self.icon)
return Response(user._icon, content_type=mime)

class ThreadController(Controller):
def create(self, request):
form = CreateThreadForm(request.post())
board = Board.retrieve(request.params['board'])
thread = Thread()
thread.title = form['title']
thread.board = board
thread.user = request.user
thread.create()
for user in board.subscribers:
user.push({
"title": res.thread.title + " - Kyokusui",
"body": "スレッドが立ちました",
"icon": self.app.convert_fullurl(request, "/user/{}/icon".format(requst.user._id))
})
return Response.json({
"_id": thread._id,
})

def retrieve(self, request):
template = self.view.get_template("thread.html")
board = Board.retrieve(request.params['board'])
thread = Thread.retrieve(request.params['thread'])
return Response.render(template, {
"board": board,
"thread": thread,
"boards": Board.list_subscribed(request.user)
})

class WebSocketController(Controller):
streams = {}
def handle(self, request):
ws = request.websocket
board = Board.retrieve(request.params['board'])
thread = Thread.retrieve(request.params['thread'])
if board._id not in self.streams:
self.streams[board._id] = dict()
if thread._id not in self.streams[board._id]:
self.streams[board._id][thread._id] = list()
self.streams[board._id][thread._id].append(ws)
db.manager.close_session()
while True:
received = ws.receive()
if received is None:
continue
try:
db.manager.start_session()
data = json.loads(received)
if data['type'] == "message":
res = Res()
res.data = json.dumps(data['data'])
res.user = request.user
res.thread = Thread.retrieve(request.params['thread'])
res.create()
mentions = re.findall(r"\>\>([0-9a-zA-Z.-_]+)", data['data']['message'])
for mention in mentions:
try:
user = User.retrieve(screen_name = mention)
user.push({
"title": res.thread.title + " - Kyokusui",
"body": res.user.name+"さんがメンションしました",
"icon": self.app.convert_fullurl(request, "/user/{}/icon".format(res.user._id))
})
except Exception as err:
print(err, mention)
pass
remove = list()
for s in self.streams[board._id][thread._id]:
try:
s.send(json.dumps({
"type": "message",
"_id": res._id,
"data": {
"message": markdown.markdown(hiroyuki(res.parsed_data["message"]), extensions=['fenced_code']),
"images": res.parsed_data["images"]
},
"user": {
"_id": res.user._id,
"name": res.user.name,
"screen_name": res.user.screen_name
},
"datetime": res.datetime.strftime("%Y-%m-%d %H:%M:%S"),
"thread": thread._id,
}))
except Exception as err:
print(err)
remove.append(s)
for s in remove:
self.streams[board._id][thread._id].remove(s)
elif data['type'] == "close":
thread = Thread.retrieve(request.params['thread'])
thread.close()
remove = list()
for s in self.streams[board._id][thread._id]:
try:
s.send(json.dumps({
"type": "close"
}))
except Exception as err:
print(err)
pass
del self.streams[board._id][thread._id]
except Exception as err:
print(err)
db.manager.rollback_session()
finally:
db.manager.close_session()
return Response()
12 changes: 12 additions & 0 deletions kyokusui/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from mitama.app.forms import Form, Field, DictField


class CreateBoardForm(Form):
name = Field(label="タイトル", required=True)
owner = Field(label="板主", required=True)

class CreateThreadForm(Form):
title = Field(label="タイトル", required=True)

class SettingForm(Form):
permissions = DictField(label="権限", listed=True)
36 changes: 36 additions & 0 deletions kyokusui/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from mitama.app import App, Router
from mitama.utils.controllers import static_files
from mitama.utils.middlewares import SessionMiddleware
from mitama.app.method import view, post

from .controller import HomeController, BoardController, ThreadController, WebSocketController, UserController
from .model import Board, Thread, Res, Permission
from .utils import hiroyuki

class App(App):
name = 'Kyokusui'
description = '業務用便所の落書き'
router = Router(
[
view("/", HomeController),
view("/settings", HomeController, 'settings'),
view("/static/<path:path>", static_files()),
view("/<board>", BoardController, 'retrieve'),
view("/<board>/<thread>", ThreadController, 'retrieve'),
view("/user/<user>/icon", UserController, 'icon'),
post("/api/v0/board", BoardController, 'create'),
post("/api/v0/board/<board>", ThreadController, 'create'),
post("/api/v0/board/<board>/subscribe", BoardController, 'subscribe'),
post("/api/v0/board/<board>/unsubscribe", BoardController, 'unsubscribe'),
view("/api/v0/board/<board>/<thread>/socket", WebSocketController),
],
middlewares=[SessionMiddleware]
)
models = [Board, Thread, Res, Permission]

@property
def view(self):
view = super().view
view.globals['permission'] = Permission.is_accepted
view.filters['hiroyuki'] = hiroyuki
return view
81 changes: 81 additions & 0 deletions kyokusui/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from mitama.db import BaseDatabase, Table, relationship
from mitama.db.model import UUID
from mitama.db.types import *
from mitama.models import User, Group, Node, permission
from datetime import datetime
import json


class Database(BaseDatabase):
pass


db = Database(prefix="kyokusui")

class Board(db.Model):
name = Column(String(255))
owner_id = Column(String(64), ForeignKey("mitama_node._id"))
owner = relationship(Node)
created = Column(DateTime, default=datetime.now)
subscribers = relationship(User, secondary="kyokusui_subscribe")

@classmethod
def list_subscribed(cls, user):
boards_ = cls.list()
boards = list()
for board in boards_:
if board.owner.object == user or (isinstance(board.owner.object, Group) and board.owner.object.is_in(user)) or user in board.subscribers:
boards.append(board)
return boards

class Thread(db.Model):
board_id = Column(String(64), ForeignKey("kyokusui_board._id"))
board = relationship(Board, backref="threads")
user_id = Column(String(64), ForeignKey("mitama_user._id"))
user = relationship(User)
created = Column(DateTime, default=datetime.now)
title = Column(String(1024))
closed = Column(Boolean, default=False)

def close(self):
self.closed = True
self.update()

class Res(db.Model):
thread_id = Column(String(64), ForeignKey("kyokusui_thread._id"))
thread = relationship(Thread, backref="res")
user_id = Column(String(64), ForeignKey("mitama_user._id"))
user = relationship(User)
datetime = Column(DateTime, default=datetime.now)
data = Column(Text)

@property
def parsed_data(self):
return json.loads(self.data)

subscribe_table = Table("kyokusui_subscribe",
db.metadata,
Column("_id", String(64), default=UUID(), primary_key=True),
Column("user_id", String(64), ForeignKey("mitama_user._id", ondelete="CASCADE")),
Column("board_id", String(64), ForeignKey("kyokusui_board._id", ondelete="CASCADE"))
)

class Subscribe(db.Model):
__table__ = subscribe_table
user_id = subscribe_table.c.user_id,
board_id = subscribe_table.c.board_id,
user = relationship(User)
board = relationship(Board)

Permission = permission(db, [
{
"name": "板を立てる",
"screen_name": "create_board"
},
{
"name": "板を閉じる",
"screen_name": "delete_board"
}
])

db.create_all()
1 change: 1 addition & 0 deletions kyokusui/static/board_form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading

0 comments on commit 5af8be8

Please sign in to comment.