Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
YuzuDice
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
YuzuDice
Commits
415410b9
Commit
415410b9
authored
May 02, 2021
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
finish
parent
d71c92e7
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
655 additions
and
106 deletions
+655
-106
src/DefaultTemplate.ts
src/DefaultTemplate.ts
+37
-6
src/app.service.ts
src/app.service.ts
+295
-44
src/bot/bot.controller.ts
src/bot/bot.controller.ts
+250
-43
src/bot/bot.service.ts
src/bot/bot.service.ts
+8
-2
src/config.ts
src/config.ts
+2
-1
src/constants.ts
src/constants.ts
+4
-2
src/entities/Group.ts
src/entities/Group.ts
+4
-0
src/entities/GroupTemplate.ts
src/entities/GroupTemplate.ts
+0
-3
src/entities/GroupUserProfile.ts
src/entities/GroupUserProfile.ts
+40
-0
src/entities/QQIDBase.ts
src/entities/QQIDBase.ts
+2
-2
src/entities/TextTemplate.ts
src/entities/TextTemplate.ts
+4
-2
src/entities/User.ts
src/entities/User.ts
+9
-1
No files found.
src/DefaultTemplate.ts
View file @
415410b9
export
const
defaultTemplateMap
=
new
Map
<
string
,
string
>
();
export
const
DefaultRollText
=
'
{{&name}} {{#reason}}因为 {{&reason}} 而{{/reason}}投掷了 {{count}} 个 {{size}} 面骰子,投掷出了 {{result}} 点。
\n
{{&formula}}={{result}}
'
;
'
{{&name}} {{#reason}}因为 {{&reason}} 而{{/reason}}投掷了 {{count}} 个 {{size}} 面骰子,投掷出了 {{result}} 点。{{#formula}}
\n
{{&formula}}{{/formula}}
'
;
defaultTemplateMap
.
set
(
'
roll
'
,
DefaultRollText
);
export
const
TooMuchCountText
=
'
{{&name}} {{#reason}}因为 {{&reason}} 而{{/reason}}投掷了 {{count}} 个 {{size}} 面骰子。
\n
骰子滚落了一地,找不到了。
'
;
defaultTemplateMap
.
set
(
'
too_much_count
'
,
TooMuchCountText
);
export
const
TooMuchSizeText
=
'
{{&name}} {{#reason}}因为 {{&reason}} 而{{/reason}}投掷了 {{count}} 个 {{size}} 面骰子。
\n
丢了个球。丢个球啊!
'
;
export
const
BadUserText
=
'
非法用户。
'
;
export
const
defaultTemplateMap
=
new
Map
<
string
,
string
>
();
defaultTemplateMap
.
set
(
'
roll
'
,
DefaultRollText
);
defaultTemplateMap
.
set
(
'
too_much_count
'
,
TooMuchCountText
);
defaultTemplateMap
.
set
(
'
too_much_size
'
,
TooMuchSizeText
);
export
const
BadUserText
=
'
您已被禁止使用该骰娘。{{#reason}}原因是: {{&reason}}{{/reason}}
'
;
defaultTemplateMap
.
set
(
'
bad_user
'
,
BadUserText
);
export
const
BadNameText
=
`你的名字 {{&name}} 不合法或者太长啦!`
;
defaultTemplateMap
.
set
(
'
bad_name
'
,
BadNameText
);
export
const
GroupNameChangedText
=
`成功修改您在本群的昵称为 {{&name}}。`
;
defaultTemplateMap
.
set
(
'
group_name_changed
'
,
GroupNameChangedText
);
export
const
GlobalNameChangedText
=
`成功修改您的昵称为 {{&name}}。`
;
defaultTemplateMap
.
set
(
'
global_name_changed
'
,
GlobalNameChangedText
);
const
banReasonText
=
'
{{#banReason}}
\n
被封禁: 是
\n
封禁原因: {{&banReason}}{{/banReason}}
'
;
export
const
GroupUserProfileText
=
`{{&displayUsername}}({{&user.id}}) 在群 {{&group.id}} 的资料:\n昵称: {{&displayUsername}}
${
banReasonText
}
`
;
defaultTemplateMap
.
set
(
'
group_user_profile
'
,
GroupUserProfileText
);
export
const
GlobalUserProfileText
=
`{{&name}}({{id}}) 的资料:\n昵称: {{&name}}
${
banReasonText
}
\n\n在过的群:{{#groupProfiles}}\n{{group.id}} -> {{&name}}{{/groupProfiles}}`
;
defaultTemplateMap
.
set
(
'
global_user_profile
'
,
GlobalUserProfileText
);
export
const
UserNotFoundText
=
`用户 {{&field}} 不存在。`
;
defaultTemplateMap
.
set
(
'
user_not_found
'
,
UserNotFoundText
);
export
const
PermissionDeniedText
=
`你没有权限进行 {{&action}} 。`
;
defaultTemplateMap
.
set
(
'
permission_denied
'
,
PermissionDeniedText
);
export
const
BadParamsText
=
`参数不正确。`
;
defaultTemplateMap
.
set
(
'
bad_params
'
,
BadParamsText
);
src/app.service.ts
View file @
415410b9
...
...
@@ -5,9 +5,10 @@ import {
NotFoundException
,
}
from
'
@nestjs/common
'
;
import
{
AppLogger
}
from
'
./app.logger
'
;
import
{
Connectio
n
}
from
'
typeorm
'
;
import
{
Brackets
,
Connection
,
I
n
}
from
'
typeorm
'
;
import
{
InjectConnection
}
from
'
@nestjs/typeorm
'
;
import
{
User
}
from
'
./entities/User
'
;
import
{
Group
}
from
'
./entities/Group
'
;
import
{
BotService
}
from
'
./bot/bot.service
'
;
import
{
UserPermissions
}
from
'
./constants
'
;
import
{
diceConfig
,
DiceConfig
}
from
'
./config
'
;
...
...
@@ -17,6 +18,8 @@ import { GroupTemplate } from './entities/GroupTemplate';
import
{
DefaultTemplate
}
from
'
./entities/DefaultTemplate
'
;
import
{
defaultTemplateMap
}
from
'
./DefaultTemplate
'
;
import
Mustache
from
'
mustache
'
;
import
{
doc
}
from
'
prettier
'
;
import
{
GroupUserProfile
}
from
'
./entities/GroupUserProfile
'
;
export
interface
RollResult
{
name
:
string
;
...
...
@@ -28,6 +31,19 @@ export interface RollResult {
results
?:
number
[];
}
export
interface
KoishiSessionLike
{
userId
?:
string
;
username
?:
string
;
groupId
?:
string
;
}
export
interface
DatabaseUserData
{
banReason
:
string
;
user
?:
User
;
group
?:
Group
;
profile
?:
GroupUserProfile
;
}
@
Injectable
()
export
class
AppService
{
config
:
DiceConfig
;
...
...
@@ -45,15 +61,37 @@ export class AppService {
rollResult
.
results
=
_
.
range
(
rollResult
.
count
).
map
(
()
=>
Math
.
floor
(
Math
.
random
()
*
rollResult
.
size
)
+
1
,
);
rollResult
.
formula
=
rollResult
.
results
.
join
(
'
+
'
);
rollResult
.
result
=
_
.
sum
(
rollResult
.
results
);
rollResult
.
formula
=
rollResult
.
count
>
1
?
`
${
rollResult
.
results
.
join
(
'
+
'
)}
=
${
rollResult
.
result
}
`
:
null
;
}
async
findOrCreateGroupUserProfile
(
user
:
User
,
group
:
Group
)
{
const
query
=
this
.
db
.
getRepository
(
GroupUserProfile
)
.
createQueryBuilder
(
'
profile
'
)
.
innerJoinAndSelect
(
'
profile.user
'
,
'
user
'
)
.
innerJoinAndSelect
(
'
profile.group
'
,
'
group
'
)
.
where
(
'
user.id = :userId
'
,
{
userId
:
user
.
id
})
.
andWhere
(
'
group.id = :groupId
'
,
{
groupId
:
group
.
id
});
let
profile
=
await
query
.
getOne
();
if
(
!
profile
)
{
profile
=
new
GroupUserProfile
();
profile
.
user
=
user
;
profile
.
group
=
group
;
profile
.
name
=
user
.
name
;
return
await
this
.
db
.
getRepository
(
GroupUserProfile
).
save
(
profile
);
}
return
profile
;
}
async
checkJoinGroup
(
userId
:
string
)
{
const
user
=
await
this
.
botService
.
findOrCreateUser
(
userId
);
if
(
user
.
checkPermissions
(
UserPermissions
.
inviteBot
))
{
return
true
;
}
else
if
(
user
.
isBanned
)
{
}
else
if
(
user
.
banReason
)
{
return
false
;
}
return
undefined
;
...
...
@@ -73,7 +111,7 @@ export class AppService {
.
getOne
();
}
private
async
getTemplate
(
key
:
string
,
groupId
:
string
)
{
private
async
getTemplate
(
key
:
string
,
groupId
?
:
string
)
{
let
template
:
TextTemplate
;
if
(
groupId
)
{
template
=
await
this
.
getTemplateForGroup
(
key
,
groupId
);
...
...
@@ -90,7 +128,7 @@ export class AppService {
return
null
;
}
private
async
renderTemplate
(
key
:
string
,
data
:
any
,
groupId
?:
string
)
{
async
renderTemplate
(
key
:
string
,
data
:
any
,
groupId
?:
string
)
{
const
template
=
await
this
.
getTemplate
(
key
,
groupId
);
if
(
template
)
{
return
template
.
render
(
data
);
...
...
@@ -100,60 +138,91 @@ export class AppService {
async
isUserHasPermissions
(
userId
:
string
,
username
:
string
,
perm
:
number
)
{
const
user
=
await
this
.
botService
.
findOrCreateUser
(
userId
,
username
);
if
(
user
.
isBanned
)
{
if
(
user
.
banReason
)
{
return
false
;
}
return
user
.
checkPermissions
(
perm
);
}
private
async
checkUserAndGroup
(
userId
:
string
,
username
:
string
,
groupId
:
string
,
)
{
const
user
=
await
this
.
botService
.
findOrCreateUser
(
userId
,
username
);
if
(
user
.
isBanned
)
{
return
false
;
private
async
getDatabaseUserData
(
userData
:
KoishiSessionLike
,
):
Promise
<
DatabaseUserData
>
{
let
user
:
User
=
null
;
if
(
userData
.
userId
)
{
user
=
await
this
.
botService
.
findOrCreateUser
(
userData
.
userId
,
userData
.
username
,
);
if
(
user
.
banReason
)
{
return
{
banReason
:
user
.
banReason
};
}
}
const
group
=
await
this
.
botService
.
findOrCreateGroup
(
groupId
);
if
(
group
.
isBanned
)
{
return
false
;
let
group
:
Group
=
null
;
if
(
userData
.
groupId
)
{
group
=
await
this
.
botService
.
findOrCreateGroup
(
userData
.
groupId
);
if
(
group
.
banReason
)
{
return
{
banReason
:
group
.
banReason
};
}
}
return
true
;
let
profile
:
GroupUserProfile
=
null
;
if
(
user
&&
group
)
{
profile
=
await
this
.
findOrCreateGroupUserProfile
(
user
,
group
);
if
(
profile
.
banReason
)
{
return
{
banReason
:
profile
.
banReason
};
}
}
return
{
user
,
group
,
profile
,
banReason
:
null
};
}
async
rollDice
(
rollResult
:
RollResult
,
userId
:
string
,
groupId
:
string
,
userData
:
KoishiSessionLike
,
):
Promise
<
string
>
{
if
(
!
(
await
this
.
checkUserAndGroup
(
userId
,
rollResult
.
name
,
groupId
)))
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{});
const
{
user
,
group
,
profile
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
,
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
if
(
rollResult
.
count
>
this
.
config
.
maxDiceCount
)
{
return
await
this
.
renderTemplate
(
'
too_much_count
'
,
rollResult
,
groupId
);
return
await
this
.
renderTemplate
(
'
too_much_count
'
,
rollResult
,
userData
.
groupId
,
);
}
if
(
rollResult
.
size
>
this
.
config
.
maxDiceSize
)
{
return
await
this
.
renderTemplate
(
'
too_much_size
'
,
rollResult
,
groupId
);
return
await
this
.
renderTemplate
(
'
too_much_size
'
,
rollResult
,
userData
.
groupId
,
);
}
rollResult
.
name
=
profile
?
profile
.
getDisplayUsername
(
userData
.
username
)
:
user
.
name
;
AppService
.
rollProcess
(
rollResult
);
return
await
this
.
renderTemplate
(
'
roll
'
,
rollResult
,
groupId
);
return
await
this
.
renderTemplate
(
'
roll
'
,
rollResult
,
userData
.
groupId
);
}
async
getGroupTemplate
(
key
:
string
,
groupId
:
string
)
{
const
group
=
await
this
.
botService
.
findOrCreateGroup
(
groupId
);
if
(
group
.
isBanned
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{});
async
getGroupTemplate
(
userData
:
KoishiSessionLike
,
key
:
string
)
{
const
{
user
,
group
,
profile
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
,
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
const
template
=
await
this
.
getTemplate
(
key
,
groupId
);
const
template
=
await
this
.
getTemplate
(
key
,
userData
.
groupId
);
if
(
template
)
{
return
template
.
display
();
}
return
`
${
key
}
=>
${
defaultTemplateMap
.
get
(
key
)
||
'
没有这个模板
'
}
`
;
}
async
getAllGroupTemplates
(
groupId
:
string
)
{
const
group
=
await
this
.
botService
.
findOrCreateGroup
(
groupId
);
if
(
group
.
isBanned
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{});
async
getAllGroupTemplates
(
userData
:
KoishiSessionLike
)
{
const
{
user
,
group
,
profile
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
,
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
const
notSetTemplateNames
=
Array
.
from
(
defaultTemplateMap
.
keys
()).
filter
(
(
tName
)
=>
!
group
.
templates
.
find
((
t
)
=>
t
.
key
===
tName
),
...
...
@@ -164,15 +233,21 @@ export class AppService {
'
\n
'
,
)}
`
;
}
async
setGroupTemplate
(
key
:
string
,
groupId
:
string
,
content
:
string
)
{
const
group
=
await
this
.
botService
.
findOrCreateGroup
(
groupId
);
if
(
group
.
isBanned
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{});
async
setGroupTemplate
(
userData
:
KoishiSessionLike
,
key
:
string
,
content
:
string
,
)
{
const
{
user
,
group
,
profile
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
,
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
if
(
!
defaultTemplateMap
.
has
(
key
))
{
return
`模板
${
key
}
不存在。`
;
}
let
template
=
await
this
.
getTemplateForGroup
(
key
,
groupId
);
let
template
=
await
this
.
getTemplateForGroup
(
key
,
userData
.
groupId
);
if
(
!
template
)
{
template
=
new
GroupTemplate
();
template
.
key
=
key
;
...
...
@@ -182,16 +257,192 @@ export class AppService {
await
this
.
db
.
getRepository
(
GroupTemplate
).
save
(
template
);
return
`成功设置自定义模板:
${
template
.
display
()}
`
;
}
async
clearGroupTemplate
(
key
:
string
,
groupId
:
string
)
{
const
group
=
await
this
.
botService
.
findOrCreateGroup
(
groupId
);
if
(
group
.
isBanned
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{});
async
clearGroupTemplate
(
userData
:
KoishiSessionLike
,
key
:
string
)
{
const
{
user
,
group
,
profile
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
,
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
const
template
=
await
this
.
getTemplateForGroup
(
key
,
groupId
);
const
template
=
await
this
.
getTemplateForGroup
(
key
,
userData
.
groupId
);
if
(
!
template
)
{
return
`自定义模板
${
key
}
没有设置过。`
;
}
await
this
.
db
.
getRepository
(
GroupTemplate
).
delete
(
template
);
return
`成功清除模板
${
key
}
`
;
}
async
getGlobalTemplate
(
userData
:
KoishiSessionLike
,
key
:
string
)
{
const
{
user
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
const
template
=
await
this
.
getTemplate
(
key
);
if
(
template
)
{
return
template
.
display
();
}
return
`
${
key
}
=>
${
defaultTemplateMap
.
get
(
key
)
||
'
没有这个模板
'
}
`
;
}
async
getAllGlobalTemplates
(
userData
:
KoishiSessionLike
)
{
const
{
user
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
const
allTemplatesList
=
Array
.
from
(
defaultTemplateMap
.
keys
());
const
templates
=
await
this
.
db
.
getRepository
(
DefaultTemplate
)
.
find
({
where
:
{
key
:
In
(
allTemplatesList
)
}
});
const
notSetTemplateNames
=
Array
.
from
(
defaultTemplateMap
.
keys
()).
filter
(
(
tName
)
=>
!
templates
.
find
((
t
)
=>
t
.
key
===
tName
),
);
return
`设置过的默认模板有:\n
${
templates
.
map
((
t
)
=>
t
.
display
())
.
join
(
'
\n
'
)}
\n\n还没有设置的默认模板有:\n
${
notSetTemplateNames
.
join
(
'
\n
'
,
)}
`
;
}
async
setGlobalTemplate
(
userData
:
KoishiSessionLike
,
key
:
string
,
content
:
string
,
)
{
const
{
user
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
if
(
!
defaultTemplateMap
.
has
(
key
))
{
return
`模板
${
key
}
不存在。`
;
}
let
template
=
await
this
.
getTemplateForGroup
(
key
,
userData
.
groupId
);
if
(
!
template
)
{
template
=
new
GroupTemplate
();
template
.
key
=
key
;
}
template
.
changeContent
(
content
);
await
this
.
db
.
getRepository
(
DefaultTemplate
).
save
(
template
);
return
`成功设置默认模板:
${
template
.
display
()}
`
;
}
async
clearGlobalTemplate
(
userData
:
KoishiSessionLike
,
key
:
string
)
{
const
{
user
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
const
template
=
await
this
.
db
.
getRepository
(
DefaultTemplate
)
.
findOne
({
where
:
{
key
}
});
if
(
!
template
)
{
return
`默认模板
${
key
}
没有设置过。`
;
}
await
this
.
db
.
getRepository
(
DefaultTemplate
).
delete
(
template
);
return
`成功清除模板
${
key
}
`
;
}
async
setGroupUsername
(
userData
:
KoishiSessionLike
,
name
:
string
)
{
const
{
user
,
group
,
profile
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
,
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
if
(
!
name
||
name
.
length
>
32
)
{
return
await
this
.
renderTemplate
(
'
bad_name
'
,
{
name
},
userData
.
groupId
);
}
profile
.
name
=
name
;
await
this
.
db
.
getRepository
(
GroupUserProfile
).
save
(
profile
);
return
await
this
.
renderTemplate
(
'
group_name_changed
'
,
{
name
},
userData
.
groupId
,
);
}
async
setGlobalUsername
(
userData
:
KoishiSessionLike
,
name
:
string
)
{
const
{
user
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
if
(
!
name
||
name
.
length
>
32
)
{
return
await
this
.
renderTemplate
(
'
bad_name
'
,
{
name
});
}
user
.
name
=
name
;
await
this
.
db
.
getRepository
(
User
).
save
(
user
);
return
await
this
.
renderTemplate
(
'
global_name_changed
'
,
{
name
});
}
async
getGroupUserProfile
(
userData
:
KoishiSessionLike
,
field
?:
string
)
{
const
{
user
,
group
,
profile
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
,
);
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
let
targetProfiles
=
[
profile
];
if
(
field
)
{
targetProfiles
=
await
this
.
db
.
getRepository
(
GroupUserProfile
)
.
createQueryBuilder
(
'
profile
'
)
.
innerJoinAndSelect
(
'
profile.user
'
,
'
user
'
)
.
innerJoinAndSelect
(
'
profile.group
'
,
'
group
'
)
.
where
(
'
group.id = :groupId
'
)
.
andWhere
(
new
Brackets
((
qb
)
=>
{
qb
.
where
(
'
profile.name = :field
'
)
.
orWhere
(
'
user.id = :field
'
)
.
orWhere
(
'
user.name = :field
'
);
}),
)
.
setParameters
({
groupId
:
group
.
id
,
field
})
.
getMany
();
if
(
!
targetProfiles
)
{
return
await
this
.
renderTemplate
(
'
user_not_found
'
,
{
field
},
userData
.
groupId
,
);
}
}
return
(
await
Promise
.
all
(
targetProfiles
.
map
((
targetProfile
)
=>
this
.
renderTemplate
(
'
group_user_profile
'
,
targetProfile
.
toDscriptionObject
(),
userData
.
groupId
,
),
),
)
).
join
(
'
\n
----------
\n
'
);
}
async
getGlobalUserProfile
(
userData
:
KoishiSessionLike
,
field
?:
string
)
{
const
{
user
,
banReason
}
=
await
this
.
getDatabaseUserData
(
userData
);
let
targetUsers
=
[
user
];
if
(
field
)
{
if
(
banReason
)
{
return
await
this
.
renderTemplate
(
'
bad_user
'
,
{
reason
:
banReason
});
}
targetUsers
=
await
this
.
db
.
getRepository
(
User
)
.
createQueryBuilder
(
'
user
'
)
.
leftJoinAndSelect
(
'
user.groupProfiles
'
,
'
profile
'
)
.
leftJoinAndSelect
(
'
profile.group
'
,
'
group
'
)
.
where
(
'
user.id = :field
'
)
.
orWhere
(
'
user.name = :field
'
)
.
setParameters
({
field
})
.
getMany
();
if
(
!
targetUsers
)
{
return
await
this
.
renderTemplate
(
'
user_not_found
'
,
{
field
},
userData
.
groupId
,
);
}
}
return
(
await
Promise
.
all
(
targetUsers
.
map
((
targetUser
)
=>
this
.
renderTemplate
(
'
global_user_profile
'
,
targetUser
.
toDscriptionObject
(),
userData
.
groupId
,
),
),
)
).
join
(
'
\n
----------
\n
'
);
}
}
src/bot/bot.controller.ts
View file @
415410b9
...
...
@@ -43,6 +43,8 @@ export class BotController {
return
msg
;
});
const
groupCtx
=
this
.
bot
.
group
();
// change here
const
privateCtx
=
this
.
bot
.
private
();
const
globalCtx
=
this
.
bot
.
all
();
groupCtx
.
middleware
(
async
(
session
,
next
)
=>
{
const
content
=
session
.
content
.
trim
();
const
rollResult
:
RollResult
=
{
...
...
@@ -55,23 +57,17 @@ export class BotController {
rollResult
.
count
=
parseInt
(
rollMatch
[
1
])
||
1
;
rollResult
.
size
=
parseInt
(
rollMatch
[
2
])
||
6
;
rollResult
.
reason
=
rollMatch
[
3
]
?
rollMatch
[
3
].
trim
()
:
null
;
await
session
.
send
(
await
this
.
appService
.
rollDice
(
rollResult
,
session
.
userId
,
session
.
groupId
,
),
);
await
session
.
send
(
await
this
.
appService
.
rollDice
(
rollResult
,
session
));
}
return
next
();
});
g
roup
Ctx
g
lobal
Ctx
.
command
(
'
rolldice
'
,
'
投掷骰子
'
)
.
option
(
'
count
'
,
'
-c <count:posint> 骰子数量
'
,
{
fallback
:
1
})
.
option
(
'
size
'
,
'
-s <count:posint> 骰子面数
'
,
{
fallback
:
6
})
.
option
(
'
reason
'
,
'
-r <reason:text> 骰子说明
'
)
.
alias
(
'
rd
'
,
'
roll
'
)
.
usage
(
'
也支持 .rd<> 和 .r<count>d<size> [reason] 这样的传统语法。
'
)
.
usage
(
'
也支持 .rd<
size
> 和 .r<count>d<size> [reason] 这样的传统语法。
'
)
.
example
(
'
.rolldice -c 2 -s 6 -r "行动判定"
'
)
.
action
(
async
(
argv
,
args
)
=>
{
const
session
=
argv
.
session
;
...
...
@@ -82,43 +78,43 @@ export class BotController {
reason
:
null
,
...
argv
.
options
,
};
return
await
this
.
appService
.
rollDice
(
rollResult
,
session
.
userId
,
session
.
groupId
,
);
return
await
this
.
appService
.
rollDice
(
rollResult
,
session
);
});
groupCtx
.
command
(
'
group.template.get [key:string]
'
,
'
获取本群自定义模板
'
)
const
groupCommand
=
groupCtx
.
command
(
'
group
'
,
'
群内指令
'
);
const
groupTemplateCommand
=
groupCommand
.
subcommand
(
'
.template
'
,
'
获取本群自定义模板
'
)
.
usage
(
`只有群管理员才能使用。key 为模板名。目前支持的模板有:
${
Array
.
from
(
defaultTemplateMap
.
keys
(),
).
join
(
'
'
)}
`
,
)
.
example
(
'
.group.template
.get
roll 获取投掷骰子的消息模板。
'
)
.
example
(
'
.group.template roll 获取投掷骰子的消息模板。
'
)
.
action
(
async
(
argv
,
key
)
=>
{
const
session
=
argv
.
session
;
if
(
!
(
await
this
.
checkGroupAdminOrPermission
(
session
,
UserPermissions
.
TemplateRead
,
UserPermissions
.
Group
TemplateRead
,
))
)
{
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
你没有权限哦。`
;
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
,
})}
${
await
this
.
appService
.
renderTemplate
(
'
permission_denied
'
,
{
action
:
'
获取本群自定义模板
'
},
session
.
groupId
,
)}
`
;
}
let
ret
;
if
(
key
)
{
ret
=
await
this
.
appService
.
getGroupTemplate
(
key
,
session
.
groupId
);
ret
=
await
this
.
appService
.
getGroupTemplate
(
session
,
key
);
}
else
{
ret
=
await
this
.
appService
.
getAllGroupTemplates
(
session
.
groupId
);
ret
=
await
this
.
appService
.
getAllGroupTemplates
(
session
);
}
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
${
ret
}
`
;
});
groupCtx
.
command
(
'
group.template.set <key:string> <content:text>
'
,
'
设置本群自定义模板
'
,
)
groupTemplateCommand
.
subcommand
(
'
.set <key:string> <content:text>
'
,
'
设置本群自定义模板
'
)
.
usage
(
`只有群管理员才能使用。key 为模板名,content为模板内容。目前支持的模板有:
${
Array
.
from
(
defaultTemplateMap
.
keys
(),
...
...
@@ -130,23 +126,35 @@ export class BotController {
if
(
!
(
await
this
.
checkGroupAdminOrPermission
(
session
,
UserPermissions
.
TemplateWrite
,
UserPermissions
.
Group
TemplateWrite
,
))
)
{
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
你没有权限哦。`
;
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
,
})}
${
await
this
.
appService
.
renderTemplate
(
'
permission_denied
'
,
{
action
:
'
设置本群自定义模板
'
},
session
.
groupId
,
)}
`
;
}
if
(
!
key
||
!
content
)
{
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
缺少参数。`
;
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
,
})}
${
await
this
.
appService
.
renderTemplate
(
'
bad_params
'
,
{},
session
.
groupId
,
)}
`
;
}
const
ret
=
await
this
.
appService
.
setGroupTemplate
(
session
,
key
,
session
.
groupId
,
content
,
);
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
${
ret
}
`
;
});
group
Ctx
.
command
(
'
group.template
.clear <key:string>
'
,
'
清除本群自定义模板
'
)
group
TemplateCommand
.
subcommand
(
'
.clear <key:string>
'
,
'
清除本群自定义模板
'
)
.
usage
(
`只有群管理员才能使用。key 为模板名。目前支持的模板有:
${
Array
.
from
(
defaultTemplateMap
.
keys
(),
...
...
@@ -158,19 +166,200 @@ export class BotController {
if
(
!
(
await
this
.
checkGroupAdminOrPermission
(
session
,
UserPermissions
.
TemplateWrite
,
UserPermissions
.
Group
TemplateWrite
,
))
)
{
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
你没有权限哦。`
;
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
,
})}
${
await
this
.
appService
.
renderTemplate
(
'
permission_denied
'
,
{
action
:
'
清除本群自定义模板
'
},
session
.
groupId
,
)}
`
;
}
if
(
!
key
)
{
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
缺少参数。`
;
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
,
})}
${
await
this
.
appService
.
renderTemplate
(
'
bad_params
'
,
{},
session
.
groupId
,
)}
`
;
}
const
ret
=
await
this
.
appService
.
clearGroupTemplate
(
session
,
key
);
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
${
ret
}
`
;
});
const
groupUserCommand
=
groupCommand
.
subcommand
(
'
.user [field:text]
'
,
'
查看群内用户信息
'
)
.
usage
(
'
带参数查看其他人的用户信息,但是只有管理员可以用。
'
)
.
example
(
'
.user 查看自己的用户信息。.user Nanahira 查看 Nanahira 的用户信息。
'
,
)
.
action
(
async
(
argv
,
field
)
=>
{
const
session
=
argv
.
session
;
if
(
field
&&
!
(
await
this
.
checkGroupAdminOrPermission
(
session
,
UserPermissions
.
GroupUserRead
,
))
)
{
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
,
})}
${
await
this
.
appService
.
renderTemplate
(
'
permission_denied
'
,
{
action
:
'
查看群员的用户信息
'
},
session
.
groupId
,
)}
`
;
}
const
ret
=
await
this
.
appService
.
getGroupUserProfile
(
session
,
field
);
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
${
ret
}
`
;
});
groupUserCommand
.
subcommand
(
'
.name <name:string>
'
,
'
修改群内用户昵称
'
)
.
example
(
'
.group.user.name Nanahira
'
)
.
action
(
async
(
argv
,
name
)
=>
{
const
session
=
argv
.
session
;
if
(
!
name
)
{
const
ret
=
await
this
.
appService
.
getGroupUserProfile
(
session
);
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
${
ret
}
`
;
}
const
ret
=
await
this
.
appService
.
setGroupUsername
(
session
,
name
);
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
${
ret
}
`
;
});
const
userCommand
=
globalCtx
.
command
(
'
account [field:text]
'
,
'
查看用户信息
'
)
.
usage
(
'
带参数查看其他人的用户信息,但是只有管理员可以用。
'
)
.
example
(
'
.account 查看自己的用户信息。.account Nanahira 查看 Nanahira 的用户信息。
'
,
)
.
action
(
async
(
argv
,
field
)
=>
{
const
session
=
argv
.
session
;
if
(
field
&&
!
(
await
this
.
checkUserPermission
(
session
,
UserPermissions
.
UserRead
))
)
{
return
await
this
.
appService
.
renderTemplate
(
'
permission_denied
'
,
{
action
:
'
查看用户信息
'
},
session
.
groupId
,
);
}
const
ret
=
await
this
.
appService
.
getGlobalUserProfile
(
session
,
field
);
return
ret
;
});
userCommand
.
subcommand
(
'
.name <name:string>
'
,
'
修改用户昵称
'
)
.
example
(
'
.account.name Nanahira 修改用户昵称为 Nanahira
'
)
.
action
(
async
(
argv
,
name
)
=>
{
const
session
=
argv
.
session
;
if
(
!
name
)
{
const
ret
=
await
this
.
appService
.
getGlobalUserProfile
(
session
);
return
ret
;
}
const
ret
=
await
this
.
appService
.
setGlobalUsername
(
session
,
name
);
return
ret
;
});
const
adminCommand
=
globalCtx
.
command
(
'
admin
'
,
'
管理接口
'
)
.
usage
(
'
这里的命令只有管理员可以用。
'
);
const
adminTemplateCommand
=
adminCommand
.
subcommand
(
'
.template
'
,
'
获取默认模板
'
)
.
usage
(
`只有群管理员才能使用。key 为模板名。目前支持的模板有:
${
Array
.
from
(
defaultTemplateMap
.
keys
(),
).
join
(
'
'
)}
`
,
)
.
example
(
'
.admin.template roll 获取投掷骰子的消息模板。
'
)
.
action
(
async
(
argv
,
key
)
=>
{
const
session
=
argv
.
session
;
if
(
!
(
await
this
.
checkUserPermission
(
session
,
UserPermissions
.
TemplateRead
,
))
)
{
return
await
this
.
appService
.
renderTemplate
(
'
permission_denied
'
,
{
action
:
'
获取默认模板
'
},
session
.
groupId
,
);
}
let
ret
;
if
(
key
)
{
ret
=
await
this
.
appService
.
getGlobalTemplate
(
session
,
key
);
}
else
{
ret
=
await
this
.
appService
.
getAllGlobalTemplates
(
session
);
}
return
ret
;
});
adminTemplateCommand
.
subcommand
(
'
.set <key:string> <content:text>
'
,
'
设置默认自定义模板
'
)
.
usage
(
`只有管理员才能使用。key 为模板名,content为模板内容。目前支持的模板有:
${
Array
.
from
(
defaultTemplateMap
.
keys
(),
).
join
(
'
'
)}
`
,
)
.
example
(
'
.admin.template.set roll <内容> 设置投掷骰子的消息模板。
'
)
.
action
(
async
(
argv
,
key
,
content
)
=>
{
const
session
=
argv
.
session
;
if
(
!
(
await
this
.
checkUserPermission
(
session
,
UserPermissions
.
TemplateWrite
,
))
)
{
return
await
this
.
appService
.
renderTemplate
(
'
permission_denied
'
,
{
action
:
'
设置默认自定义模板
'
},
session
.
groupId
,
);
}
if
(
!
key
||
!
content
)
{
return
await
this
.
appService
.
renderTemplate
(
'
bad_params
'
,
{},
session
.
groupId
,
);
}
const
ret
=
await
this
.
appService
.
clearGroupTemplate
(
const
ret
=
await
this
.
appService
.
setGlobalTemplate
(
session
,
key
,
session
.
groupId
,
content
,
);
return
`
${
segment
(
'
at
'
,
{
id
:
session
.
userId
})}
${
ret
}
`
;
return
ret
;
});
adminTemplateCommand
.
subcommand
(
'
.clear <key:string>
'
,
'
清除默认自定义模板
'
)
.
usage
(
`只有群管理员才能使用。key 为模板名。目前支持的模板有:
${
Array
.
from
(
defaultTemplateMap
.
keys
(),
).
join
(
'
'
)}
`
,
)
.
example
(
'
.admin.template.set roll <内容> 设置投掷骰子的消息模板。
'
)
.
action
(
async
(
argv
,
key
)
=>
{
const
session
=
argv
.
session
;
if
(
!
(
await
this
.
checkUserPermission
(
session
,
UserPermissions
.
TemplateWrite
,
))
)
{
return
await
this
.
appService
.
renderTemplate
(
'
permission_denied
'
,
{
action
:
'
清除默认自定义模板
'
},
session
.
groupId
,
);
}
if
(
!
key
)
{
return
await
this
.
appService
.
renderTemplate
(
'
bad_params
'
,
{},
session
.
groupId
,
);
}
const
ret
=
await
this
.
appService
.
clearGlobalTemplate
(
session
,
key
);
return
ret
;
});
}
async
checkGroupAdminOrPermission
(
...
...
@@ -191,11 +380,29 @@ export class BotController {
)
{
return
(
(
await
this
.
checkGroupAdmin
(
session
))
||
(
await
this
.
appService
.
isUserHasPermissions
(
session
.
userId
,
session
.
username
,
UserPermissions
.
TemplateRead
,
))
(
await
this
.
checkUserPermission
(
session
,
perm
))
);
}
async
checkUserPermission
(
session
:
Session
<
never
,
never
,
'
onebot
'
,
keyof
Session
.
Events
,
|
keyof
Session
.
MessageType
|
'
role
'
|
'
ban
'
|
keyof
Session
.
GroupMemberChangeType
|
'
poke
'
|
'
lucky-king
'
|
'
honor
'
>
,
perm
:
number
,
)
{
return
await
this
.
appService
.
isUserHasPermissions
(
session
.
userId
,
session
.
username
,
perm
,
);
}
async
checkGroupAdmin
(
...
...
src/bot/bot.service.ts
View file @
415410b9
...
...
@@ -17,7 +17,10 @@ export class BotService {
async
findOrCreateUser
(
id
:
string
,
name
?:
string
)
{
const
repo
=
this
.
db
.
getRepository
(
User
);
let
ent
=
await
repo
.
findOne
({
where
:
{
id
}
});
let
ent
=
await
repo
.
findOne
({
where
:
{
id
},
relations
:
[
'
groupProfiles
'
,
'
groupProfiles.group
'
],
});
if
(
ent
)
{
if
(
!
ent
.
name
&&
name
)
{
ent
.
name
=
name
;
...
...
@@ -39,7 +42,10 @@ export class BotService {
}
async
findOrCreateGroup
(
id
:
string
)
{
const
repo
=
this
.
db
.
getRepository
(
Group
);
let
ent
=
await
repo
.
findOne
({
where
:
{
id
},
relations
:
[
'
templates
'
]
});
let
ent
=
await
repo
.
findOne
({
where
:
{
id
},
relations
:
[
'
templates
'
,
'
userProfiles
'
,
'
userProfiles.user
'
],
});
if
(
ent
)
{
return
ent
;
}
...
...
src/config.ts
View file @
415410b9
...
...
@@ -3,6 +3,7 @@ import { User } from './entities/User';
import
{
Group
}
from
'
./entities/Group
'
;
import
{
DefaultTemplate
}
from
'
./entities/DefaultTemplate
'
;
import
{
GroupTemplate
}
from
'
./entities/GroupTemplate
'
;
import
{
GroupUserProfile
}
from
'
./entities/GroupUserProfile
'
;
export
function
dbConfig
()
{
return
{
...
...
@@ -17,7 +18,7 @@ export function typeormConfig(): TypeOrmModuleOptions {
return
{
name
:
'
app
'
,
type
:
'
mysql
'
,
entities
:
[
User
,
Group
,
DefaultTemplate
,
GroupTemplate
],
// entities here
entities
:
[
User
,
Group
,
DefaultTemplate
,
GroupTemplate
,
GroupUserProfile
],
// entities here
synchronize
:
true
,
...
dbConfig
(),
};
...
...
src/constants.ts
View file @
415410b9
export
const
UserPermissions
=
{
// read
UserRead
:
0x1
,
GroupRead
:
0x2
,
Group
User
Read
:
0x2
,
TemplateRead
:
0x4
,
GroupTemplateRead
:
0x8
,
// write
UserWrite
:
0x100
,
GroupWrite
:
0x200
,
Group
User
Write
:
0x200
,
TemplateWrite
:
0x400
,
GroupTemplateWrite
:
0x800
,
// others
inviteBot
:
0x10000
,
};
src/entities/Group.ts
View file @
415410b9
import
{
QQIDBase
}
from
'
./QQIDBase
'
;
import
{
Column
,
Entity
,
OneToMany
}
from
'
typeorm
'
;
import
{
GroupTemplate
}
from
'
./GroupTemplate
'
;
import
{
GroupUserProfile
}
from
'
./GroupUserProfile
'
;
@
Entity
()
export
class
Group
extends
QQIDBase
{
@
OneToMany
((
type
)
=>
GroupTemplate
,
(
template
)
=>
template
.
group
)
templates
:
GroupTemplate
[];
@
OneToMany
((
type
)
=>
GroupUserProfile
,
(
profile
)
=>
profile
.
group
)
userProfiles
:
GroupUserProfile
[];
renderText
(
key
:
string
,
data
:
any
)
{
const
template
=
this
.
templates
.
find
((
t
)
=>
key
===
t
.
key
);
if
(
this
.
templates
)
{
...
...
src/entities/GroupTemplate.ts
View file @
415410b9
...
...
@@ -20,7 +20,4 @@ export class GroupTemplate extends TextTemplate {
@
ManyToOne
((
type
)
=>
Group
,
(
group
)
=>
group
.
templates
)
group
:
Group
;
@
RelationId
((
template
:
GroupTemplate
)
=>
template
.
group
)
groupId
:
string
;
}
src/entities/GroupUserProfile.ts
0 → 100644
View file @
415410b9
import
{
TimeBase
}
from
'
./TimeBase
'
;
import
{
Column
,
Entity
,
Index
,
ManyToOne
,
PrimaryGeneratedColumn
,
}
from
'
typeorm
'
;
import
{
User
}
from
'
./User
'
;
import
{
Group
}
from
'
./Group
'
;
@
Entity
()
export
class
GroupUserProfile
extends
TimeBase
{
@
PrimaryGeneratedColumn
(
'
uuid
'
)
id
:
string
;
@
ManyToOne
((
type
)
=>
User
,
(
user
)
=>
user
.
groupProfiles
)
user
:
User
;
@
ManyToOne
((
type
)
=>
Group
,
(
group
)
=>
group
.
userProfiles
)
group
:
Group
;
@
Index
()
@
Column
(
'
varchar
'
,
{
nullable
:
true
,
length
:
32
})
name
:
string
;
@
Column
(
'
varchar
'
,
{
nullable
:
true
,
length
:
100
})
banReason
:
string
;
getDisplayUsername
(
fallback
?:
string
)
{
return
this
.
name
||
this
.
user
.
name
||
fallback
;
}
toDscriptionObject
()
{
return
{
displayUsername
:
this
.
getDisplayUsername
(),
...
this
,
};
}
}
src/entities/QQIDBase.ts
View file @
415410b9
...
...
@@ -5,6 +5,6 @@ export class QQIDBase extends TimeBase {
@
PrimaryColumn
(
'
varchar
'
,
{
length
:
12
})
id
:
string
;
@
Column
(
'
tinyint
'
,
{
default
:
0
})
isBanned
:
number
;
@
Column
(
'
varchar
'
,
{
nullable
:
true
,
length
:
10
0
})
banReason
:
string
;
}
src/entities/TextTemplate.ts
View file @
415410b9
...
...
@@ -9,11 +9,13 @@ export class TextTemplate extends TimeBase {
content
:
string
;
changeContent
(
content
:
string
)
{
this
.
content
=
Buffer
.
from
(
decode
(
content
),
'
utf-8
'
).
toString
(
'
base64
'
);
//this.content = Buffer.from(decode(content), 'utf-8').toString('base64');
this
.
content
=
decode
(
content
);
}
getContent
()
{
return
Buffer
.
from
(
this
.
content
,
'
base64
'
).
toString
(
'
utf-8
'
);
//return Buffer.from(this.content, 'base64').toString('utf-8');
return
this
.
content
;
}
render
(
data
:
any
)
{
...
...
src/entities/User.ts
View file @
415410b9
import
{
QQIDBase
}
from
'
./QQIDBase
'
;
import
{
Column
,
Entity
,
Index
}
from
'
typeorm
'
;
import
{
Column
,
Entity
,
Index
,
OneToMany
}
from
'
typeorm
'
;
import
{
GroupUserProfile
}
from
'
./GroupUserProfile
'
;
@
Entity
()
export
class
User
extends
QQIDBase
{
...
...
@@ -10,7 +11,14 @@ export class User extends QQIDBase {
@
Column
(
'
int
'
,
{
default
:
0
,
unsigned
:
true
})
// default with all read permissions
permissions
:
number
;
@
OneToMany
((
type
)
=>
GroupUserProfile
,
(
profile
)
=>
profile
.
user
)
groupProfiles
:
GroupUserProfile
[];
checkPermissions
(
permissionNeeded
:
number
)
{
return
!!
(
this
.
permissions
&
permissionNeeded
);
}
toDscriptionObject
()
{
return
this
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment