Skip to content

Commit ac8c545

Browse files
committed
add clan and login to web
1 parent 84d116b commit ac8c545

44 files changed

Lines changed: 5103 additions & 24 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

deploy/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ services:
1414
web:
1515
image: zzbslayer/kokkoro_bot:latest
1616
ports:
17-
- "5100:5001"
17+
- "5560:5001"
1818
volumes:
1919
- ~/.kokkoro:/root/.kokkoro
2020
command: python3.8 -u /bot/run_web.py

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ services:
1515
web:
1616
image: zzbslayer/kokkoro_bot:latest
1717
ports:
18-
- "5100:5001"
18+
- "5560:5001"
1919
volumes:
2020
- ./:/bot/
2121
- ~/.kokkoro:/root/.kokkoro

kokkoro/bot/discord/discord_util.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ def remove_mention_me(raw_message) -> (str, bool):
1616
Pattern in official document is <@![a-z0-9A-Z]+>
1717
e.g. <@!12345>
1818
19-
But the `at` sent by ios discord is <@[a-z0-9A-Z]>
19+
But the `at` sent by iOS discord is <@[a-z0-9A-Z]>
2020
e.g. <@12345>
2121
2222
So temp solution is <@!?[a-z0-9A-Z]+>
2323
'''
24-
dc_at_pattern = r'<@!?[a-z0-9A-Z]+>'
24+
dc_at_pattern = r'<@!?[a-z0-9A-Z]+>'
2525
def normalize_message(raw_message: str) -> str:
2626
"""
2727
规范化 at 信息,"<@!123> waht<@!312>a12" => "@123 waht @312 a12"
@@ -33,7 +33,7 @@ def normalize_message(raw_message: str) -> str:
3333

3434
def normalize_at(raw_at):
3535
"""
36-
规范化 at 信息,"<@!123>" => " @123 "
36+
规范化 at 信息,"<@!123>" => " @123 "
3737
ios: "<@123>" => " @123 "
3838
"""
39-
return f' @{raw_at[3:-1]} ' if '!' in raw_at else f' @{raw_at[2:-1]} '
39+
return f' @{raw_at[3:-1]} ' if '!' in raw_at else f' @{raw_at[2:-1]} '

kokkoro/config_example/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import matplotlib.font_manager as font_manager
55

66
from .__bot__ import *
7+
from .__web__ import *
78

89
for module in MODULES_ON:
910
try:

kokkoro/config_example/__web__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
PUBLIC_ADDRESS="http://DOMAIN_OR_IP_ADDRESS:5560"
2+
PUBLIC_BASEPATH="/"

kokkoro/modules/pcrclanbattle/clanbattle/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .argparse import ArgParser
66
from .exception import *
77

8+
from kokkoro import config
89
from kokkoro.typing import *
910
from kokkoro.common_interface import KokkoroBot, EventInterface
1011
from kokkoro.service import Service
@@ -22,7 +23,7 @@ def cb_cmd(prefixes, parser:ArgParser) -> Callable:
2223
prefixes = cb_prefix(prefixes)
2324
if not isinstance(prefixes, Iterable):
2425
raise ValueError('`name` of cb_cmd must be `str` or `Iterable[str]`')
25-
26+
2627
def deco(func):
2728
@wraps(func)
2829
async def wrapper(bot: KokkoroBot, ev: EventInterface):
@@ -44,6 +45,8 @@ async def wrapper(bot: KokkoroBot, ev: EventInterface):
4445

4546

4647
from .cmdv2 import *
48+
if config.ENABLE_WEB:
49+
from .cmd_web import *
4750

4851

4952
QUICK_START = f'''
@@ -105,4 +108,4 @@ async def cb_help(bot: KokkoroBot, ev:EventInterface):
105108
# content='命令一览表')
106109
# await session.send(msg)
107110

108-
from . import report
111+
from . import report
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import json
2+
import os
3+
from datetime import datetime, timedelta
4+
import time
5+
from hashlib import sha256
6+
from typing import Dict, Union
7+
from urllib.parse import urljoin
8+
9+
from .webmaster import WebMaster
10+
11+
from .argparse import ArgParser, ArgHolder, ParseResult
12+
from .argparse.argtype import *
13+
from . import sv, cb_cmd, cb_prefix
14+
from . import cb_cmd
15+
from kokkoro import config
16+
from kokkoro.common_interface import KokkoroBot, EventInterface
17+
from kokkoro.service import Service
18+
from kokkoro.priv import ADMIN, SUPERUSER
19+
from kokkoro.util import rand_string, add_salt_and_hash
20+
21+
svweb = Service('web')
22+
@svweb.scheduled_job('cron', hour='5')
23+
async def drop_expired_logins():
24+
now = datetime.now()
25+
wm = WebMaster()
26+
wm.del_login_by_time(now)
27+
28+
EXPIRED_TIME = 7 * 24 * 60 * 60 # 7 days
29+
LOGIN_AUTH_COOKIE_NAME = 'yobot_login'
30+
# this need be same with static/password.js
31+
FRONTEND_SALT = '14b492a3-a40a-42fc-a236-e9a9307b47d2'
32+
33+
34+
@cb_cmd(('登录', 'login'), ArgParser('!登录'))
35+
async def login(bot:KokkoroBot, ev:EventInterface, args:ParseResult):
36+
if False and "this message is from group": # FIXME
37+
return '请私聊使用'
38+
39+
wm = WebMaster()
40+
uid = ev.get_author_id()
41+
gid = ev.get_group_id()
42+
auth = ev.get_author().get_priv()
43+
44+
member = wm.get_member(uid, gid)
45+
if member is None:
46+
await bot.kkr_send(ev, '请先加入公会')
47+
return
48+
member['authority_group'] = 100
49+
if auth == SUPERUSER:
50+
member['authority_group'] = 1
51+
elif auth == ADMIN:
52+
member['authority_group'] = 10
53+
wm.mod_member(member)
54+
55+
user = wm.get_or_add_user(uid, rand_string(16))
56+
login_code = rand_string(6)
57+
user['login_code'] = login_code
58+
user['login_code_available'] = True
59+
user['login_code_expire_time'] = int(time.time()) + 60
60+
wm.mod_user(user)
61+
62+
url = urljoin(
63+
config.PUBLIC_ADDRESS,
64+
'{}login/c/#uid={}&key={}'.format(
65+
config.PUBLIC_BASEPATH,
66+
user['uid'],
67+
login_code,
68+
)
69+
)
70+
await bot.kkr_send_dm(uid, url)
71+
72+
@cb_cmd(('重置密码', 'reset-password'), ArgParser('!重置密码'))
73+
async def reset_password(bot:KokkoroBot, ev:EventInterface, args:ParseResult):
74+
if False and "this message is from group": # FIXME
75+
return '请私聊使用'
76+
reply = f'您的临时密码是:{reset_pwd(ev)}'
77+
await bot.kkr_send_dm(ev.get_author_id(), reply)
78+
79+
def reset_pwd(ev:EventInterface):
80+
wm = WebMaster()
81+
user = wm.get_or_add_user(ev.get_author_id(), rand_string(16))
82+
raw_pwd = rand_string(8)
83+
frontend_salted_pwd = add_salt_and_hash(raw_pwd + user['uid'], FRONTEND_SALT)
84+
user['password'] = add_salt_and_hash(frontend_salted_pwd, user['salt'])
85+
user['privacy'] = 0
86+
user['must_change_password'] = 1
87+
wm.mod_user(user)
88+
wm.del_login(user['uid'])
89+
return raw_pwd
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from datetime import datetime, timezone, timedelta
2+
3+
from kokkoro.common_interface import EventInterface
4+
from .dao.sqlitedao import ClanDao, MemberDao, UserDao, LoginDao
5+
from .exception import NotFoundError
6+
7+
class WebMaster():
8+
def __init__(self):
9+
super().__init__()
10+
self.clandao = ClanDao()
11+
self.memberdao = MemberDao()
12+
self.userdao = UserDao()
13+
self.logindao = LoginDao()
14+
15+
16+
def get_clan(self, gid):
17+
return self.clandao.findone(gid)
18+
def get_clan_by_uid(self, uid):
19+
return self.clandao.find_by_uid(uid)
20+
21+
22+
def get_member(self, uid, gid):
23+
mem = self.memberdao.find_one(uid, gid)
24+
return mem if mem else None
25+
def get_member_by_uid(self, uid):
26+
mems = self.memberdao.find_by(uid=uid)
27+
return mems if mems else None
28+
def mod_member(self, member:dict):
29+
return self.memberdao.modify(member)
30+
31+
32+
def get_or_add_user(self, uid, salt):
33+
return self.userdao.get_or_add(uid, salt)
34+
def get_user(self, uid):
35+
return self.userdao.find_one(uid)
36+
def mod_user(self, user:dict):
37+
return self.userdao.modify(user)
38+
39+
40+
def add_login(self, uid, auth_cookie, auth_cookie_expire_time):
41+
return self.logindao.add(uid, auth_cookie, auth_cookie_expire_time)
42+
def get_login(self, uid, auth_cookie):
43+
return self.logindao.find_one(uid, auth_cookie)
44+
def mod_login(self, login:dict):
45+
return self.logindao.modify(login)
46+
def del_login(self, uid):
47+
return self.logindao.delete(uid)
48+
def del_login_by_time(self, time):
49+
return self.logindao.delete_by_time(self, time)
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
from kokkoro.service import BroadcastTag, BroadcastService
22

3-
sv9 = BroadcastService('pcr-arena-reminder-utc9',
4-
broadcast_tag=[BroadcastTag.cn_broadcast, BroadcastTag.tw_broadcast], enable_on_default=False, help_='背刺时间提醒(UTC+9)')
3+
sv9 = BroadcastService('pcr-arena-reminder-utc9',
4+
broadcast_tag=[BroadcastTag.cn_broadcast, BroadcastTag.tw_broadcast],
5+
enable_on_default=False, help_='背刺时间提醒(UTC+9)')
56

6-
sv8 = BroadcastService('pcr-arena-reminder-utc8',
7-
broadcast_tag=BroadcastTag.jp_broadcast,
7+
sv8 = BroadcastService('pcr-arena-reminder-utc8',
8+
broadcast_tag=BroadcastTag.jp_broadcast,
89
enable_on_default=False, help_='背刺时间提醒(UTC+8)')
910

10-
msg = '主人様、准备好背刺了吗?'
11+
msg = '主さま、准备好背刺了吗?'
1112

1213
@sv8.scheduled_job('cron', hour='14', minute='45', misfire_grace_time=60*10)
1314
async def pcr_reminder_utc8():
1415
await sv8.broadcast(msg)
1516

1617
@sv9.scheduled_job('cron', hour='13', minute='45', misfire_grace_time=60*10)
1718
async def pcr_reminder_utc9():
18-
await sv9.broadcast(msg)
19+
await sv9.broadcast(msg)

kokkoro/util.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,23 @@
77
import json
88
import re
99
import importlib
10+
import random
1011

1112
from collections import defaultdict
1213
from datetime import datetime, timedelta
1314
from matplotlib import pyplot as plt
1415
from PIL import Image
1516
from io import BytesIO
17+
from hashlib import sha256
1618

1719
import itertools
1820

1921
import kokkoro
2022
from kokkoro import config
2123
from kokkoro.typing import Iterable
2224

25+
charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
26+
2327
def escape(s: str, *, escape_comma: bool = True) -> str:
2428
s = s.replace('&', '&amp;') \
2529
.replace('[', '&#91;') \
@@ -118,7 +122,7 @@ def left_time(self, key) -> float:
118122

119123
class DailyNumberLimiter:
120124
tz = pytz.timezone('Asia/Shanghai')
121-
125+
122126
def __init__(self, max_num):
123127
self.today = -1
124128
self.count = defaultdict(int)
@@ -167,3 +171,8 @@ def load_modules(module_dir, module_prefix):
167171

168172
load_module(f'{module_prefix}.{m.group(1)}')
169173

174+
def rand_string(n=16):
175+
return ''.join(random.choice(charset) for _ in range(n))
176+
177+
def add_salt_and_hash(raw: str, salt: str):
178+
return sha256((raw + salt).encode()).hexdigest()

0 commit comments

Comments
 (0)