mirror of https://github.com/andrigamerita/simpkey
wip
This commit is contained in:
parent
b958350d0f
commit
dbd58fc39d
|
@ -1,8 +1,8 @@
|
|||
import Koa from 'koa';
|
||||
import { router, render } from '.';
|
||||
import { router } from './router';
|
||||
import config from './config';
|
||||
import session from 'koa-session';
|
||||
import bodyParser from 'koa-bodyparser';
|
||||
import { render } from './render';
|
||||
|
||||
|
||||
const app = new Koa();
|
||||
|
@ -12,7 +12,6 @@ console.log('Simpkey v' + config.version);
|
|||
app.use(bodyParser());
|
||||
app.use(render);
|
||||
app.use(router.routes());
|
||||
app.use(router.allowedMethods());
|
||||
|
||||
console.log('App launched!');
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import { Context } from 'koa';
|
||||
|
||||
export const die = (ctx: Context, error: string): Promise<void> => {
|
||||
ctx.status = 400;
|
||||
return ctx.render('error', { error });
|
||||
};
|
100
src/index.ts
100
src/index.ts
|
@ -1,100 +0,0 @@
|
|||
import { Context, DefaultState } from 'koa';
|
||||
import views from 'koa-views';
|
||||
import Router from 'koa-router';
|
||||
import config from './config';
|
||||
import { signIn, api, i } from './misskey';
|
||||
import { Note } from './models/Note';
|
||||
import { User } from './models/User';
|
||||
|
||||
export const die = (ctx: Context, error: string): Promise<void> => {
|
||||
ctx.status = 400;
|
||||
return ctx.render('error', { error });
|
||||
};
|
||||
|
||||
export const render = views(__dirname + '/views', {
|
||||
extension: 'pug', options: {
|
||||
...config,
|
||||
getAcct: (user: User) => user.host ? `@${user.username}@${user.host}` : `@${user.username}`,
|
||||
getUserName: (user: User) => user.name || user.username,
|
||||
}
|
||||
});
|
||||
|
||||
export const router = new Router<DefaultState, Context>();
|
||||
|
||||
const staticRouting = [
|
||||
[ 'about', 'Simpkey について' ],
|
||||
[ 'terms', '利用規約' ],
|
||||
[ 'privacy-policy', 'プライバシーポリシー' ],
|
||||
];
|
||||
|
||||
for (const [ name, title ] of staticRouting) {
|
||||
router.get('/' + name, async (ctx, next) => {
|
||||
await ctx.render(name, { title });
|
||||
await next();
|
||||
});
|
||||
}
|
||||
|
||||
async function timeline(ctx: Context, host: string, endpoint: string, timelineName: string, token: string) {
|
||||
const user = await i(host, token);
|
||||
|
||||
const timeline = await api<Note[]>(host, endpoint, { i: token });
|
||||
await ctx.render('timeline', {
|
||||
title: timelineName + ' - Simpkey',
|
||||
user, timeline, timelineName
|
||||
});
|
||||
}
|
||||
|
||||
router.get('/ltl', async (ctx, next) => {
|
||||
const token = ctx.cookies.get('i');
|
||||
const host = ctx.cookies.get('host');
|
||||
if (!token || !host) {
|
||||
await die(ctx, 'ログインしてください');
|
||||
} else {
|
||||
const meta = await api<any>(host, 'meta', { i: token });
|
||||
if (meta.disableLocalTimeline) {
|
||||
await die(ctx, 'ローカルタイムラインは無効化されています');
|
||||
} else {
|
||||
await timeline(ctx, host, 'notes/local-timeline', 'ローカルタイムライン', token);
|
||||
}
|
||||
}
|
||||
await next();
|
||||
});
|
||||
|
||||
router.get('/', async (ctx, next) => {
|
||||
const token = ctx.cookies.get('i');
|
||||
const host = ctx.cookies.get('host');
|
||||
if (!token || !host) {
|
||||
console.log('no session so show top page');
|
||||
await ctx.render('index', {
|
||||
title: 'Simpkey'
|
||||
});
|
||||
} else {
|
||||
console.log('show timeline with the session');
|
||||
await timeline(ctx, host, 'notes/timeline', 'ホームタイムライン', token);
|
||||
}
|
||||
await next();
|
||||
});
|
||||
|
||||
router.post('/', async (ctx) => {
|
||||
const {
|
||||
host,
|
||||
username,
|
||||
password,
|
||||
token
|
||||
} = ctx.request.body;
|
||||
if (!host || !username || !password) {
|
||||
await die(ctx, 'パラメータが足りません');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const { id, i } = await signIn(host, username, password, token);
|
||||
ctx.cookies.set('id', id);
|
||||
ctx.cookies.set('host', host);
|
||||
ctx.cookies.set('i', i);
|
||||
console.log('login as ' + username);
|
||||
ctx.redirect('/');
|
||||
} catch (err) {
|
||||
await die(ctx, err.message);
|
||||
console.error(err);
|
||||
}
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
import config from './config';
|
||||
import views from 'koa-views';
|
||||
import { User } from './models/User';
|
||||
import { Note } from './models/Note';
|
||||
|
||||
export const render = views(__dirname + '/views', {
|
||||
extension: 'pug', options: {
|
||||
...config,
|
||||
getAcct: (user: User) => user.host ? `@${user.username}@${user.host}` : `@${user.username}`,
|
||||
getUserName: (user: User) => user.name || user.username,
|
||||
getVisibility: (note: Note) => {
|
||||
let icon: string;
|
||||
switch (note.visibility) {
|
||||
case 'public':
|
||||
icon = '🌐';
|
||||
break;
|
||||
case 'home':
|
||||
icon = '🏠';
|
||||
break;
|
||||
case 'followers':
|
||||
icon = '🔒';
|
||||
break;
|
||||
case 'specified':
|
||||
icon = '✉️';
|
||||
break;
|
||||
default:
|
||||
icon = '❓';
|
||||
break;
|
||||
}
|
||||
if (note.localOnly) icon += '☣';
|
||||
return icon;
|
||||
},
|
||||
}
|
||||
});
|
|
@ -0,0 +1,146 @@
|
|||
import { Context, DefaultState } from 'koa';
|
||||
import Router from 'koa-router';
|
||||
import { signIn, api, i } from './misskey';
|
||||
import { Note } from './models/Note';
|
||||
import { die } from './die';
|
||||
|
||||
export const router = new Router<DefaultState, Context>();
|
||||
|
||||
const staticRouting = [
|
||||
[ 'about', 'Simpkey について' ],
|
||||
[ 'terms', '利用規約' ],
|
||||
[ 'privacy-policy', 'プライバシーポリシー' ],
|
||||
[ 'settings', '設定' ],
|
||||
];
|
||||
|
||||
for (const [ name, title ] of staticRouting) {
|
||||
router.get('/' + name, async ctx => {
|
||||
await ctx.render(name, { title });
|
||||
});
|
||||
}
|
||||
|
||||
async function timeline(ctx: Context, host: string, endpoint: string, timelineName: string, token: string) {
|
||||
const user = await i(host, token);
|
||||
const timeline = await api<Note[]>(host, endpoint, { i: token });
|
||||
|
||||
await ctx.render('timeline', {
|
||||
title: timelineName + ' - Simpkey',
|
||||
user, timeline, timelineName
|
||||
});
|
||||
}
|
||||
|
||||
router.get('/', async ctx => {
|
||||
const token = ctx.cookies.get('i');
|
||||
const host = ctx.cookies.get('host');
|
||||
if (!token || !host) {
|
||||
console.log('no session so show top page');
|
||||
await ctx.render('index', {
|
||||
title: 'Simpkey'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await timeline(ctx, host, 'notes/timeline', 'ホームタイムライン', token);
|
||||
});
|
||||
|
||||
router.get('/ltl', async ctx => {
|
||||
const token = ctx.cookies.get('i');
|
||||
const host = ctx.cookies.get('host');
|
||||
if (!token || !host) {
|
||||
await die(ctx, 'ログインしてください');
|
||||
return;
|
||||
}
|
||||
const meta = await api<any>(host, 'meta', { i: token });
|
||||
if (meta.disableLocalTimeline) {
|
||||
await die(ctx, 'ローカルタイムラインは無効化されています');
|
||||
} else {
|
||||
await timeline(ctx, host, 'notes/local-timeline', 'ローカルタイムライン', token);
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/stl', async ctx => {
|
||||
const token = ctx.cookies.get('i');
|
||||
const host = ctx.cookies.get('host');
|
||||
if (!token || !host) {
|
||||
await die(ctx, 'ログインしてください');
|
||||
return;
|
||||
}
|
||||
const meta = await api<any>(host, 'meta', { i: token });
|
||||
if (meta.disableLocalTimeline) {
|
||||
await die(ctx, 'ソーシャルタイムラインは無効化されています');
|
||||
} else {
|
||||
await timeline(ctx, host, 'notes/hybrid-timeline', 'ソーシャルタイムライン', token);
|
||||
}
|
||||
});
|
||||
router.get('/gtl', async ctx => {
|
||||
const token = ctx.cookies.get('i');
|
||||
const host = ctx.cookies.get('host');
|
||||
if (!token || !host) {
|
||||
await die(ctx, 'ログインしてください');
|
||||
return;
|
||||
}
|
||||
|
||||
const meta = await api<any>(host, 'meta', { i: token });
|
||||
if (meta.disableGlobalTimeline) {
|
||||
await die(ctx, 'グローバルタイムラインは無効化されています');
|
||||
} else {
|
||||
await timeline(ctx, host, 'notes/global-timeline', 'グローバルタイムライン', token);
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/', async ctx => {
|
||||
const {
|
||||
host,
|
||||
username,
|
||||
password,
|
||||
token
|
||||
} = ctx.request.body;
|
||||
if (!host || !username || !password) {
|
||||
await die(ctx, 'パラメータが足りません');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const { id, i } = await signIn(host, username, password, token);
|
||||
ctx.cookies.set('id', id);
|
||||
ctx.cookies.set('host', host);
|
||||
ctx.cookies.set('i', i);
|
||||
console.log('login as ' + username);
|
||||
ctx.redirect('/');
|
||||
} catch (err) {
|
||||
await die(ctx, err.message);
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/action/:action', async ctx => {
|
||||
const i = ctx.cookies.get('i');
|
||||
const host = ctx.cookies.get('host');
|
||||
if (!i || !host) {
|
||||
await die(ctx, 'ログインしてください');
|
||||
return;
|
||||
}
|
||||
|
||||
const action = ctx.params.action as string;
|
||||
switch (action) {
|
||||
case 'create-note': {
|
||||
const { text } = ctx.request.body;
|
||||
if (!text) await die(ctx, 'テキストがありません');
|
||||
await api(host, 'notes/create', { text, i });
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx.redirect('back', '/');
|
||||
});
|
||||
|
||||
router.post('/logout', ctx => {
|
||||
ctx.cookies.set('id');
|
||||
ctx.cookies.set('host');
|
||||
ctx.cookies.set('i');
|
||||
ctx.redirect('/');
|
||||
});
|
||||
|
||||
// Return 404 for other pages
|
||||
router.all('(.*)', async ctx => {
|
||||
ctx.status = 404;
|
||||
await die(ctx, 'ページが見つかりませんでした');
|
||||
});
|
|
@ -8,8 +8,9 @@ mixin note(note)
|
|||
|
|
||||
span(style="color: gray")= getAcct(note.user)
|
||||
p= note.text
|
||||
aside= new Date(note.createdAt).toLocaleString()
|
||||
aside= note.visibility
|
||||
aside
|
||||
!=getVisibility(note)
|
||||
!=new Date(note.createdAt).toLocaleString()
|
||||
|
||||
html
|
||||
head
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
extends _base
|
||||
|
||||
block content
|
||||
h2 設定
|
||||
h3 ユーザー
|
||||
form(action="/logout", method="post")
|
||||
button(type="submit") ログアウト
|
|
@ -5,7 +5,7 @@ block content
|
|||
p: b=getUserName(user)
|
||||
|
|
||||
span(style="color: gray")= getAcct(user)
|
||||
form(action="/note", method="post")
|
||||
form(action="/action/create-note", method="post")
|
||||
textarea(name="text", placeholder="今何してる?" style="max-width: 100%; min-width: 100%; height: 6em; margin-bottom: 8px")
|
||||
button(type="submit") ノート
|
||||
hr
|
||||
|
@ -17,6 +17,8 @@ block content
|
|||
a(href="/stl") ソーシャル
|
||||
| ・
|
||||
a(href="/gtl") グローバル
|
||||
| ・
|
||||
a(href="/settings") 設定
|
||||
h2= timelineName
|
||||
each note in timeline
|
||||
if (note.renote)
|
||||
|
|
Loading…
Reference in New Issue