mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-02 03:06:52 -05:00
882 lines
25 KiB
JavaScript
882 lines
25 KiB
JavaScript
const {
|
|
UserInputError,
|
|
AuthenticationError,
|
|
gql,
|
|
} = require("apollo-server-express")
|
|
const shuffle = require("../utils/shuffleArray")
|
|
const User = require("../mongoose-models/user")
|
|
const Suggested = require("../mongoose-models/suggested")
|
|
const Summary = require("../mongoose-models/summary")
|
|
const VotedPerson = require("../mongoose-models/votedperson")
|
|
const State = require("../mongoose-models/state")
|
|
const Player = require("../mongoose-models/player")
|
|
const Placement = require("../mongoose-models/placement")
|
|
|
|
const typeDef = gql`
|
|
extend type Query {
|
|
plusInfo: PlusGeneralInfo
|
|
hasAccess(discord_id: String!): String
|
|
xPowers(discord_id: String!): [Int]!
|
|
suggestions: [Suggested!]
|
|
vouches: [User!]
|
|
usersForVoting: UsersForVoting!
|
|
summaries: [Summary!]
|
|
}
|
|
|
|
extend type Mutation {
|
|
addSuggestion(
|
|
discord_id: String!
|
|
server: String!
|
|
region: String!
|
|
description: String!
|
|
): Boolean!
|
|
addVouch(discord_id: String!, server: String!, region: String!): Boolean!
|
|
addVotes(votes: [VoteInput!]!): Boolean!
|
|
startVoting(ends: String!): Boolean!
|
|
endVoting: Boolean!
|
|
}
|
|
|
|
"+1 or +2 LFG server on Discord"
|
|
enum PlusServer {
|
|
ONE
|
|
TWO
|
|
}
|
|
|
|
"Region used for voting"
|
|
enum PlusRegion {
|
|
EU
|
|
NA
|
|
}
|
|
|
|
type PlusGeneralInfo {
|
|
voting_ends: String
|
|
voter_count: Int!
|
|
eligible_voters: Int!
|
|
}
|
|
|
|
type Suggested {
|
|
discord_id: String!
|
|
discord_user: User!
|
|
suggester_discord_id: String!
|
|
suggester_discord_user: User!
|
|
plus_region: PlusRegion!
|
|
plus_server: PlusServer!
|
|
description: String!
|
|
createdAt: String!
|
|
}
|
|
|
|
"Status with +1 and +2 related things"
|
|
type PlusStatus {
|
|
membership_status: PlusServer
|
|
vouch_status: PlusServer
|
|
plus_region: PlusRegion
|
|
can_vouch: PlusServer
|
|
voucher_discord_id: String
|
|
voucher_user: User
|
|
can_vouch_again_after: String
|
|
}
|
|
|
|
extend type User {
|
|
plus: PlusStatus
|
|
}
|
|
|
|
input VoteInput {
|
|
discord_id: String!
|
|
score: Int!
|
|
}
|
|
|
|
type VotedPerson {
|
|
discord_id: String!
|
|
voter_discord_id: String!
|
|
plus_server: String!
|
|
month: Int!
|
|
year: Int!
|
|
"Voting result -2 to +2 (-1 to +1 cross-region)"
|
|
score: Int!
|
|
stale: Boolean!
|
|
}
|
|
|
|
type Score {
|
|
total: Float!
|
|
eu_count: [Int]
|
|
na_count: [Int]
|
|
}
|
|
|
|
"Voting result of a player"
|
|
type Summary {
|
|
discord_id: String!
|
|
discord_user: User!
|
|
plus_server: PlusServer!
|
|
month: Int!
|
|
year: Int!
|
|
suggested: Boolean
|
|
vouched: Boolean
|
|
"Average of all scores of the voters for the month 0% to 100%"
|
|
score: Score!
|
|
new: Boolean!
|
|
}
|
|
|
|
type UsersForVoting {
|
|
users: [User!]!
|
|
suggested: [Suggested!]!
|
|
votes: [VotedPerson!]!
|
|
}
|
|
`
|
|
|
|
const validateVotes = (votes, users, suggested, user) => {
|
|
const region = user.plus.plus_region
|
|
|
|
votes.forEach((vote) => {
|
|
const { discord_id, score } = vote
|
|
|
|
let votedUser = users.find(
|
|
(userInServer) => userInServer.discord_id === discord_id
|
|
)
|
|
|
|
if (!votedUser) {
|
|
votedUser = suggested.find(
|
|
(suggested) => suggested.discord_user.discord_id === discord_id
|
|
)
|
|
if (!votedUser)
|
|
throw new UserInputError(
|
|
`Invalid user voted on with the id ${discord_id}`
|
|
)
|
|
|
|
const plus_region_of_suggested = votedUser.plus_region
|
|
votedUser = votedUser.discord_user
|
|
votedUser.plus = {}
|
|
votedUser.plus.plus_region = plus_region_of_suggested
|
|
}
|
|
|
|
if (score !== -2 && score !== -1 && score !== 1 && score !== 2)
|
|
throw new Error(`Invalid score provided: ${score}`)
|
|
|
|
if ((score === -2 || score === 2) && region !== votedUser.plus.plus_region)
|
|
throw new Error("Score of -2 or 2 given cross region")
|
|
})
|
|
}
|
|
|
|
const resolvers = {
|
|
Query: {
|
|
hasAccess: async (root, args) => {
|
|
const user = await User.findOne({ discord_id: args.discord_id }).catch(
|
|
(e) => {
|
|
throw (
|
|
(new Error(),
|
|
{
|
|
invalidArgs: args,
|
|
})
|
|
)
|
|
}
|
|
)
|
|
|
|
if (!user || !user.plus) return false
|
|
|
|
const { membership_status, vouch_status } = user.plus
|
|
let membership_code =
|
|
membership_status === "TWO" || vouch_status === "TWO" ? "TWO" : null
|
|
membership_code =
|
|
membership_status === "ONE" || vouch_status === "ONE"
|
|
? "ONE"
|
|
: membership_code
|
|
|
|
return membership_code
|
|
},
|
|
plusInfo: async (root, args, ctx) => {
|
|
if (!ctx.user) return null
|
|
if (!ctx.user.plus || !ctx.user.plus.membership_status) {
|
|
return null
|
|
}
|
|
|
|
const state = await State.findOne({})
|
|
|
|
const votedPeople = await VotedPerson.find({
|
|
stale: false,
|
|
plus_server: ctx.user.plus.membership_status,
|
|
})
|
|
|
|
const votedIds = new Set()
|
|
|
|
votedPeople.forEach((vote) => {
|
|
votedIds.add(vote.voter_discord_id)
|
|
})
|
|
|
|
const eligible_voters = await User.countDocuments({
|
|
"plus.membership_status": ctx.user.plus.membership_status,
|
|
})
|
|
|
|
return {
|
|
voting_ends: state.voting_ends,
|
|
voter_count: votedIds.size,
|
|
eligible_voters,
|
|
}
|
|
},
|
|
xPowers: async (root, args, ctx) => {
|
|
const user = await User.findOne({ discord_id: args.discord_id })
|
|
if (!user || !user.twitter_name) return [null, null, null, null]
|
|
|
|
const twitter = user.twitter_name.toLowerCase()
|
|
|
|
const player = await Player.findOne({
|
|
twitter,
|
|
})
|
|
|
|
if (!player) return [null, null, null, null]
|
|
|
|
const placements = await Placement.find({ unique_id: player.unique_id })
|
|
|
|
return placements.reduce(
|
|
(acc, cur) => {
|
|
const modeIndex = cur.mode - 1
|
|
const xPower = Math.floor(cur.x_power / 100) * 100
|
|
|
|
if (acc[modeIndex] === null) {
|
|
acc[modeIndex] = xPower
|
|
} else if (xPower > acc[modeIndex]) {
|
|
acc[modeIndex] = xPower
|
|
}
|
|
|
|
return acc
|
|
},
|
|
[null, null, null, null]
|
|
)
|
|
},
|
|
usersForVoting: async (root, args, ctx) => {
|
|
if (!ctx.user) throw new UserInputError("Not logged in")
|
|
if (!ctx.user.plus || !ctx.user.plus.membership_status)
|
|
throw new UserInputError("Not plus server member")
|
|
const plus_server = ctx.user.plus.membership_status
|
|
|
|
const users = await User.find({
|
|
$or: [
|
|
{
|
|
"plus.membership_status": plus_server,
|
|
},
|
|
|
|
{ "plus.vouch_status": plus_server },
|
|
],
|
|
}).catch((e) => {
|
|
throw (
|
|
(new Error(),
|
|
{
|
|
error: e,
|
|
})
|
|
)
|
|
})
|
|
|
|
const suggested = await Suggested.find({ plus_server })
|
|
.populate("discord_user")
|
|
.populate("suggester_discord_user")
|
|
.catch((e) => {
|
|
throw (
|
|
(new Error(),
|
|
{
|
|
error: e,
|
|
})
|
|
)
|
|
})
|
|
|
|
const votes = await VotedPerson.find({
|
|
voter_discord_id: ctx.user.discord_id,
|
|
})
|
|
|
|
shuffle(users)
|
|
shuffle(suggested)
|
|
|
|
return { users, suggested, votes }
|
|
},
|
|
suggestions: (root, args, ctx) => {
|
|
if (!ctx.user || !ctx.user.plus || !ctx.user.plus.membership_status)
|
|
return null
|
|
const searchCriteria =
|
|
ctx.user.plus.membership_status === "ONE" ? {} : { plus_server: "TWO" }
|
|
return Suggested.find(searchCriteria)
|
|
.populate("discord_user")
|
|
.populate("suggester_discord_user")
|
|
.sort({ plus_server: "asc", createdAt: "desc" })
|
|
.catch((e) => {
|
|
throw new UserInputError(e.message, {
|
|
invalidArgs: args,
|
|
})
|
|
})
|
|
},
|
|
vouches: (root, args, { user }) => {
|
|
if (!user || !user.plus || !user.plus.membership_status) return null
|
|
const searchCriteria =
|
|
user.plus.membership_status === "ONE"
|
|
? { "plus.vouch_status": { $ne: null } }
|
|
: { "plus.vouch_status": "TWO" }
|
|
return User.find(searchCriteria)
|
|
.sort({ "plus.vouch_status": "asc" })
|
|
.populate("plus.voucher_user")
|
|
},
|
|
summaries: (root, args, ctx) => {
|
|
if (!ctx.user || !ctx.user.plus || !ctx.user.plus.membership_status)
|
|
return null
|
|
const searchCriteria =
|
|
ctx.user.plus.membership_status === "ONE" ? {} : { plus_server: "TWO" }
|
|
|
|
return Summary.find(searchCriteria)
|
|
.populate("discord_user")
|
|
.sort({ year: "desc", month: "desc", "score.total": "desc" })
|
|
},
|
|
},
|
|
Mutation: {
|
|
addSuggestion: async (root, args, ctx) => {
|
|
if (!ctx.user) throw new AuthenticationError("Not logged in.")
|
|
if (!ctx.user.plus || !ctx.user.plus.membership_status) {
|
|
throw new AuthenticationError("Not plus member.")
|
|
}
|
|
|
|
const state = await State.findOne({})
|
|
if (state && !!state.voting_ends) {
|
|
throw new UserInputError(
|
|
"Voting already started so suggesting not possible"
|
|
)
|
|
}
|
|
|
|
const user = await User.findOne({ discord_id: args.discord_id }).catch(
|
|
(e) => {
|
|
throw (
|
|
(new Error(),
|
|
{
|
|
invalidArgs: args,
|
|
error: e,
|
|
})
|
|
)
|
|
}
|
|
)
|
|
|
|
const suggestion = await Suggested.findOne({
|
|
suggester_discord_id: ctx.user.discord_id,
|
|
}).catch((e) => {
|
|
throw (
|
|
(new Error(),
|
|
{
|
|
invalidArgs: args,
|
|
error: e,
|
|
})
|
|
)
|
|
})
|
|
|
|
if (suggestion) throw new UserInputError("Already suggested this month.")
|
|
|
|
const duplicateSuggestion = await Suggested.findOne({
|
|
discord_id: args.discord_id,
|
|
plus_server: args.server,
|
|
}).catch((e) => {
|
|
throw (
|
|
(new Error(),
|
|
{
|
|
invalidArgs: args,
|
|
error: e,
|
|
})
|
|
)
|
|
})
|
|
|
|
if (duplicateSuggestion)
|
|
throw new UserInputError(
|
|
"This user has already been suggested this month."
|
|
)
|
|
|
|
if (!user)
|
|
throw new UserInputError("Suggested user not sendou.ink member.")
|
|
|
|
if (args.server !== "ONE" && args.server !== "TWO")
|
|
throw new UserInputError("Server arg has to be 'ONE' or 'TWO'.")
|
|
|
|
if (
|
|
user.plus.membership_status === args.server ||
|
|
user.plus.membership_status === "ONE" ||
|
|
user.plus.vouch_status === args.server ||
|
|
user.plus.vouch_status === "ONE"
|
|
)
|
|
throw new UserInputError(
|
|
"Suggested user is already a member of the server."
|
|
)
|
|
|
|
const date = new Date()
|
|
const month = date.getMonth() + 1
|
|
const year = date.getFullYear()
|
|
|
|
const kickedSummary = await Summary.findOne({
|
|
discord_id: args.discord_id,
|
|
plus_server: args.server,
|
|
suggested: { $in: [null, false] },
|
|
month,
|
|
year,
|
|
score: { $lt: 0 },
|
|
})
|
|
|
|
if (kickedSummary) {
|
|
throw new UserInputError(
|
|
"Can't suggest because user got kicked less than month ago."
|
|
)
|
|
}
|
|
|
|
if (ctx.user.plus.membership_status !== "ONE" && args.server === "ONE")
|
|
throw new UserInputError("Can't suggest to +1 without being +1 member.")
|
|
|
|
if (args.region !== "EU" && args.region !== "NA")
|
|
throw new UserInputError("Region arg has to be 'NA' or 'EU'.")
|
|
|
|
if (args.description.length > 1000)
|
|
throw new UserInputError("Description has to be below 1000 characters.")
|
|
|
|
const newSuggestion = new Suggested({
|
|
discord_id: args.discord_id,
|
|
suggester_discord_id: ctx.user.discord_id,
|
|
plus_region: args.region,
|
|
plus_server: args.server,
|
|
description: args.description,
|
|
})
|
|
|
|
await newSuggestion.save().catch((e) => {
|
|
throw (
|
|
(new Error(),
|
|
{
|
|
invalidArgs: args,
|
|
})
|
|
)
|
|
})
|
|
|
|
return true
|
|
},
|
|
addVouch: async (root, args, ctx) => {
|
|
if (!ctx.user) throw new AuthenticationError("Not logged in.")
|
|
if (!ctx.user.plus || !ctx.user.plus.membership_status) {
|
|
throw new AuthenticationError("Not plus member.")
|
|
}
|
|
|
|
const state = await State.findOne({})
|
|
if (state && !!state.voting_ends) {
|
|
throw new UserInputError(
|
|
"Voting already started so suggesting not possible"
|
|
)
|
|
}
|
|
|
|
if (args.server !== "ONE" && args.server !== "TWO")
|
|
throw new UserInputError("Invalid plus server given.")
|
|
if (args.region !== "EU" && args.region !== "NA")
|
|
throw new UserInputError("Invalid region given.")
|
|
|
|
const can_vouch = ctx.user.plus.can_vouch
|
|
if (!can_vouch || (can_vouch !== "ONE" && args.server === "ONE"))
|
|
throw new UserInputError("No privileges to vouch.")
|
|
|
|
if (ctx.user.plus.can_vouch_again_after)
|
|
throw new UserInputError(
|
|
"No privileges to vouch right now due to previous vouch getting kicked."
|
|
)
|
|
|
|
const user = await User.findOne({ discord_id: args.discord_id })
|
|
|
|
if (!user)
|
|
throw new UserInputError("User vouched is not a sendou.ink member.")
|
|
|
|
if (
|
|
user.plus &&
|
|
(user.plus.membership_status === args.server ||
|
|
user.plus.vouch_status === args.server ||
|
|
user.plus.membership_status === "ONE" ||
|
|
user.plus.vouch_status === "ONE")
|
|
)
|
|
throw new UserInputError("User already has access.")
|
|
|
|
const date = new Date()
|
|
const month = date.getMonth() + 1
|
|
const year = date.getFullYear()
|
|
|
|
const kickedSummary = await Summary.findOne({
|
|
discord_id: args.discord_id,
|
|
plus_server: args.server,
|
|
suggested: { $in: [null, false] },
|
|
month,
|
|
year,
|
|
score: { $lt: 0 },
|
|
})
|
|
|
|
if (kickedSummary) {
|
|
throw new UserInputError(
|
|
"Can't vouch because user got kicked less than month ago."
|
|
)
|
|
}
|
|
|
|
if (!user.plus) user.plus = {}
|
|
user.plus.vouch_status = args.server
|
|
user.plus.voucher_discord_id = ctx.user.discord_id
|
|
if (!user.plus.plus_region) user.plus.plus_region = args.region
|
|
|
|
const vouchingUser = await User.findOne({
|
|
discord_id: ctx.user.discord_id,
|
|
})
|
|
|
|
vouchingUser.plus.can_vouch = undefined
|
|
|
|
await user.save()
|
|
await vouchingUser.save()
|
|
await Suggested.deleteOne({
|
|
discord_id: args.discord_id,
|
|
plus_server: args.server,
|
|
})
|
|
|
|
return true
|
|
},
|
|
addVotes: async (root, args, ctx) => {
|
|
if (!ctx.user) throw new AuthenticationError("Not logged in.")
|
|
if (!ctx.user.plus || !ctx.user.plus.membership_status) {
|
|
throw new AuthenticationError("Not plus member.")
|
|
}
|
|
|
|
const state = await State.findOne({})
|
|
|
|
const date = new Date()
|
|
if (!state.voting_ends || state.voting_ends < date.getTime())
|
|
throw new UserInputError("Voting is not open right now")
|
|
|
|
const votedUsers = {}
|
|
|
|
args.votes.forEach((vote) => {
|
|
if (votedUsers[vote.discord_id])
|
|
throw new UserInputVote(
|
|
`Duplicate vote with the id ${vote.discord_id}`
|
|
)
|
|
votedUsers[vote.discord_id] = true
|
|
})
|
|
|
|
const plus_server = ctx.user.plus.membership_status
|
|
|
|
const users = await User.find({
|
|
$or: [
|
|
{
|
|
"plus.membership_status": plus_server,
|
|
},
|
|
|
|
{ "plus.vouch_status": plus_server },
|
|
],
|
|
})
|
|
|
|
const suggested = await Suggested.find({ plus_server })
|
|
.populate("discord_user")
|
|
.populate("suggester_discord_user")
|
|
|
|
if (users.length + suggested.length !== args.votes.length)
|
|
throw new UserInputError("Invalid number of votes provided")
|
|
|
|
validateVotes(args.votes, users, suggested, ctx.user)
|
|
|
|
const year = date.getFullYear()
|
|
const month = date.getMonth() + 1
|
|
await VotedPerson.deleteMany({
|
|
voter_discord_id: ctx.user.discord_id,
|
|
stale: false,
|
|
})
|
|
|
|
const toInsert = args.votes.map((vote) => ({
|
|
discord_id: vote.discord_id,
|
|
voter_discord_id: ctx.user.discord_id,
|
|
month,
|
|
year,
|
|
plus_server,
|
|
score: vote.score,
|
|
stale: false,
|
|
}))
|
|
await VotedPerson.insertMany(toInsert)
|
|
|
|
return true
|
|
},
|
|
startVoting: async (root, args, ctx) => {
|
|
if (!ctx.user) throw new AuthenticationError("Not logged in.")
|
|
if (ctx.user.discord_id !== process.env.ADMIN_ID)
|
|
throw new AuthenticationError("Not admin.")
|
|
|
|
await State.findOneAndUpdate({}, { voting_ends: args.ends })
|
|
|
|
return true
|
|
},
|
|
endVoting: async (root, args, ctx) => {
|
|
if (!ctx.user) throw new AuthenticationError("Not logged in.")
|
|
if (ctx.user.discord_id !== process.env.ADMIN_ID)
|
|
throw new AuthenticationError("Not admin.")
|
|
|
|
const date = new Date()
|
|
const year = date.getFullYear()
|
|
const month = date.getMonth() + 1
|
|
const votes = await VotedPerson.find({ stale: false })
|
|
.populate("discord_user")
|
|
.populate("voter_discord_user")
|
|
|
|
const suggested = await Suggested.find({}).populate("discord_user")
|
|
|
|
const plus_one_voted = {}
|
|
const plus_two_voted = {}
|
|
|
|
votes.forEach((vote) => {
|
|
const {
|
|
discord_id,
|
|
plus_server,
|
|
score,
|
|
discord_user,
|
|
voter_discord_user,
|
|
} = vote
|
|
|
|
let voted_plus_region = discord_user.plus.plus_region
|
|
const voter_plus_region = voter_discord_user.plus.plus_region
|
|
|
|
if (!voted_plus_region) {
|
|
const suggestedUser = suggested.find(
|
|
(suggested) => suggested.discord_id === discord_id
|
|
)
|
|
voted_plus_region = suggestedUser.plus_region
|
|
}
|
|
|
|
const plus_x_voted =
|
|
plus_server === "ONE" ? plus_one_voted : plus_two_voted
|
|
if (!plus_x_voted.hasOwnProperty(discord_id)) {
|
|
plus_x_voted[discord_id] = {}
|
|
plus_x_voted[discord_id].same_region = []
|
|
plus_x_voted[discord_id].other_region = []
|
|
}
|
|
|
|
if (!plus_x_voted[discord_id].plus_region) {
|
|
let plus_region =
|
|
discord_user.plus && discord_user.plus.plus_region
|
|
? discord_user.plus.plus_region
|
|
: null
|
|
if (!plus_region)
|
|
plus_region = suggested.find(
|
|
(suggester) => suggester.discord_id === discord_id
|
|
).plus_region
|
|
plus_x_voted[discord_id].plus_region = plus_region
|
|
}
|
|
|
|
if (!plus_x_voted[discord_id].membership_status) {
|
|
const membership_status =
|
|
discord_user.plus && discord_user.plus.membership_status
|
|
? discord_user.plus.membership_status
|
|
: null
|
|
plus_x_voted[discord_id].membership_status = membership_status
|
|
}
|
|
|
|
if (
|
|
!plus_x_voted[discord_id].can_not_vouch &&
|
|
discord_user.plus &&
|
|
discord_user.plus.can_vouch_again_after
|
|
) {
|
|
if (
|
|
parseInt(discord_user.plus.can_vouch_again_after) >
|
|
new Date().getTime()
|
|
)
|
|
plus_x_voted[discord_id].can_not_vouch = true
|
|
}
|
|
|
|
if (
|
|
!plus_x_voted[discord_id].voucher_discord_id &&
|
|
discord_user.plus &&
|
|
discord_user.plus.voucher_discord_id &&
|
|
plus_server === discord_user.plus.vouch_status
|
|
) {
|
|
plus_x_voted[discord_id].voucher_discord_id =
|
|
discord_user.plus.voucher_discord_id
|
|
}
|
|
|
|
const arrToPushTo =
|
|
voted_plus_region === voter_plus_region
|
|
? plus_x_voted[discord_id].same_region
|
|
: plus_x_voted[discord_id].other_region
|
|
|
|
arrToPushTo.push(score)
|
|
})
|
|
|
|
const votingArrays = [plus_one_voted, plus_two_voted]
|
|
|
|
const summariesToInsert = []
|
|
const userUpdates = []
|
|
const preventVouchingUpdates = []
|
|
|
|
votingArrays.forEach((votingArray, index) => {
|
|
const arrays_plus_server = index === 0 ? "ONE" : "TWO"
|
|
Object.keys(votingArray).forEach((discord_id) => {
|
|
const {
|
|
same_region,
|
|
other_region,
|
|
plus_region,
|
|
membership_status,
|
|
can_not_vouch,
|
|
voucher_discord_id,
|
|
dont_update,
|
|
} = votingArray[discord_id]
|
|
|
|
const same_total = same_region.reduce((acc, cur) => acc + cur)
|
|
const other_total = other_region.reduce((acc, cur) => acc + cur)
|
|
|
|
const total_score = +(
|
|
((same_total / same_region.length +
|
|
other_total / other_region.length +
|
|
3) /
|
|
6) *
|
|
100
|
|
).toFixed(2)
|
|
|
|
const countReducer = (acc, cur) => {
|
|
const scoreMap = { "-2": 0, "-1": 1, "1": 2, "2": 3 }
|
|
const scoreIndex = scoreMap[cur]
|
|
if (!acc[scoreIndex]) acc[scoreIndex] = 1
|
|
else acc[scoreIndex] = acc[scoreIndex] + 1
|
|
|
|
return acc
|
|
}
|
|
|
|
const same_count = same_region.reduce(countReducer, [0, 0, 0, 0])
|
|
const other_count = other_region.reduce(countReducer, [0, 0, 0, 0])
|
|
|
|
const summary = {
|
|
discord_id,
|
|
plus_server: arrays_plus_server,
|
|
month,
|
|
year,
|
|
score: {
|
|
total: total_score,
|
|
eu_count: plus_region === "EU" ? same_count : other_count,
|
|
na_count: plus_region === "EU" ? other_count : same_count,
|
|
},
|
|
}
|
|
|
|
if (total_score < 50 && membership_status === arrays_plus_server) {
|
|
if (membership_status === "TWO")
|
|
userUpdates.push(() =>
|
|
User.updateOne(
|
|
{ discord_id },
|
|
{ $set: { "plus.membership_status": null } }
|
|
)
|
|
)
|
|
else
|
|
userUpdates.push(() =>
|
|
User.updateOne(
|
|
{ discord_id },
|
|
{ $set: { "plus.membership_status": "TWO" } }
|
|
)
|
|
)
|
|
} else if (
|
|
total_score >= 50 &&
|
|
membership_status !== arrays_plus_server &&
|
|
!dont_update
|
|
) {
|
|
userUpdates.push(() =>
|
|
User.updateOne(
|
|
{ discord_id },
|
|
{ $set: { "plus.membership_status": arrays_plus_server } }
|
|
)
|
|
)
|
|
|
|
if (arrays_plus_server === "ONE" && plus_two_voted[discord_id]) {
|
|
plus_two_voted[discord_id].dont_update = true
|
|
}
|
|
}
|
|
|
|
if (voucher_discord_id) {
|
|
summary.vouched = true
|
|
if (total_score < 50) {
|
|
const now = new Date()
|
|
const can_vouch_again_after = new Date(
|
|
now.getFullYear(),
|
|
now.getMonth() + 5,
|
|
1
|
|
)
|
|
preventVouchingUpdates.push(() =>
|
|
User.updateOne(
|
|
{ discord_id: voucher_discord_id },
|
|
{
|
|
$set: {
|
|
"plus.can_vouch_again_after": can_vouch_again_after,
|
|
"plus.can_vouch": null,
|
|
},
|
|
}
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
if (!voucher_discord_id && membership_status !== arrays_plus_server) {
|
|
summary.suggested = true
|
|
userUpdates.push(() =>
|
|
User.updateOne(
|
|
{ discord_id },
|
|
{ $set: { "plus.plus_region": plus_region } }
|
|
)
|
|
)
|
|
}
|
|
|
|
if (
|
|
arrays_plus_server === "ONE" &&
|
|
total_score >= 90 &&
|
|
!can_not_vouch
|
|
) {
|
|
userUpdates.push(() =>
|
|
User.updateOne(
|
|
{ discord_id },
|
|
{ $set: { "plus.can_vouch": "ONE" } }
|
|
)
|
|
)
|
|
} else if (
|
|
arrays_plus_server === "TWO" &&
|
|
total_score >= 80 &&
|
|
!can_not_vouch
|
|
) {
|
|
userUpdates.push(() =>
|
|
User.updateOne(
|
|
{ discord_id },
|
|
{ $set: { "plus.can_vouch": "TWO" } }
|
|
)
|
|
)
|
|
}
|
|
|
|
summariesToInsert.push(summary)
|
|
})
|
|
})
|
|
|
|
await User.updateMany(
|
|
{ "plus.can_vouch": { $exists: true } },
|
|
{ $set: { "plus.can_vouch": null } }
|
|
)
|
|
|
|
await User.updateMany(
|
|
{ "plus.can_vouch_again_after": { $lte: new Date() } },
|
|
{ $set: { "plus.can_vouch_again_after": null } }
|
|
)
|
|
|
|
await User.updateMany(
|
|
{ "plus.vouch_status": { $exists: true } },
|
|
{ $set: { "plus.vouch_status": null } }
|
|
)
|
|
|
|
await User.updateMany(
|
|
{ "plus.voucher_discord_id": { $exists: true } },
|
|
{ $set: { "plus.voucher_discord_id": null } }
|
|
)
|
|
|
|
userUpdates.forEach(async (userUpdateFunction) => {
|
|
await userUpdateFunction()
|
|
})
|
|
|
|
preventVouchingUpdates.forEach(async (userUpdateFunction) => {
|
|
await userUpdateFunction()
|
|
})
|
|
|
|
await Summary.insertMany(summariesToInsert)
|
|
await Suggested.deleteMany({})
|
|
|
|
await VotedPerson.deleteMany({ stale: true })
|
|
await VotedPerson.updateMany({}, { $set: { stale: true } })
|
|
await State.updateOne({}, { $set: { voting_ends: null } })
|
|
|
|
return true
|
|
},
|
|
},
|
|
}
|
|
|
|
module.exports = {
|
|
Plus: typeDef,
|
|
plusResolvers: resolvers,
|
|
}
|