3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-15 05:41:51 +00:00

Fix merge conflicts, remove PluginRuntimeError changes

This commit is contained in:
Dragory 2019-07-11 12:52:02 +03:00
commit f190e73c28
5 changed files with 342 additions and 0 deletions

63
src/data/GuildVCAlerts.ts Normal file
View file

@ -0,0 +1,63 @@
import { BaseGuildRepository } from "./BaseGuildRepository";
import { getRepository, Repository } from "typeorm";
import { VCAlert } from "./entities/VCAlert";
export class GuildVCAlerts extends BaseGuildRepository {
private allAlerts: Repository<VCAlert>;
constructor(guildId) {
super(guildId);
this.allAlerts = getRepository(VCAlert);
}
async getOutdatedAlerts(): Promise<VCAlert[]> {
return this.allAlerts
.createQueryBuilder()
.where("guild_id = :guildId", { guildId: this.guildId })
.andWhere("expires_at <= NOW()")
.getMany();
}
async getAllGuildAlerts(): Promise<VCAlert[]> {
return this.allAlerts
.createQueryBuilder()
.where("guild_id = :guildId", { guildId: this.guildId })
.getMany();
}
async getAlertsByUserId(userId: string): Promise<VCAlert[]> {
return this.allAlerts.find({
where: {
guild_id: this.guildId,
user_id: userId,
},
});
}
async getAlertsByRequestorId(requestorId: string): Promise<VCAlert[]> {
return this.allAlerts.find({
where: {
guild_id: this.guildId,
requestor_id: requestorId,
},
});
}
async delete(id) {
await this.allAlerts.delete({
guild_id: this.guildId,
id,
});
}
async add(requestorId: string, userId: string, channelId: string, expiresAt: string, body: string) {
await this.allAlerts.insert({
guild_id: this.guildId,
requestor_id: requestorId,
user_id: userId,
channel_id: channelId,
expires_at: expiresAt,
body,
});
}
}

View file

@ -0,0 +1,20 @@
import { Entity, Column, PrimaryColumn } from "typeorm";
@Entity("vc_alerts")
export class VCAlert {
@Column()
@PrimaryColumn()
id: number;
@Column() guild_id: string;
@Column() requestor_id: string;
@Column() user_id: string;
@Column() channel_id: string;
@Column() expires_at: string;
@Column() body: string;
}

View file

@ -0,0 +1,58 @@
import { MigrationInterface, QueryRunner, Table } from "typeorm";
export class AddVCAlertTable1561391921385 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.createTable(
new Table({
name: "vc_alerts",
columns: [
{
name: "id",
type: "int",
unsigned: true,
isGenerated: true,
generationStrategy: "increment",
isPrimary: true,
},
{
name: "guild_id",
type: "bigint",
unsigned: true,
},
{
name: "requestor_id",
type: "bigint",
unsigned: true,
},
{
name: "user_id",
type: "bigint",
unsigned: true,
},
{
name: "channel_id",
type: "bigint",
unsigned: true,
},
{
name: "expires_at",
type: "datetime",
},
{
name: "body",
type: "text",
},
],
indices: [
{
columnNames: ["guild_id", "user_id"],
},
],
}),
);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.dropTable("vc_alerts", true, false, true);
}
}

199
src/plugins/LocateUser.ts Normal file
View file

@ -0,0 +1,199 @@
import { decorators as d, IPluginOptions, getInviteLink, logger } from "knub";
import { ZeppelinPlugin } from "./ZeppelinPlugin";
import humanizeDuration from "humanize-duration";
import { Message, Member, Guild, TextableChannel, VoiceChannel, Channel, User } from "eris";
import { GuildVCAlerts } from "../data/GuildVCAlerts";
import moment = require("moment");
import { resolveMember, sorter, createChunkedMessage, errorMessage, successMessage } from "../utils";
const ALERT_LOOP_TIME = 30 * 1000;
interface ILocatePluginConfig {
can_where: boolean;
can_alert: boolean;
}
export class LocatePlugin extends ZeppelinPlugin<ILocatePluginConfig> {
public static pluginName = "locate_user";
private alerts: GuildVCAlerts;
private outdatedAlertsTimeout;
private usersWithAlerts: string[] = [];
getDefaultOptions(): IPluginOptions<ILocatePluginConfig> {
return {
config: {
can_where: false,
can_alert: false,
},
overrides: [
{
level: ">=50",
config: {
can_where: true,
can_alert: true,
},
},
],
};
}
onLoad() {
this.alerts = GuildVCAlerts.getGuildInstance(this.guildId);
this.outdatedAlertsLoop();
this.fillActiveAlertsList();
}
async outdatedAlertsLoop() {
const outdatedAlerts = await this.alerts.getOutdatedAlerts();
for (const alert of outdatedAlerts) {
await this.alerts.delete(alert.id);
await this.removeUserIDFromActiveAlerts(alert.user_id);
}
this.outdatedAlertsTimeout = setTimeout(() => this.outdatedAlertsLoop(), ALERT_LOOP_TIME);
}
async fillActiveAlertsList() {
const allAlerts = await this.alerts.getAllGuildAlerts();
allAlerts.forEach(alert => {
if (!this.usersWithAlerts.includes(alert.user_id)) {
this.usersWithAlerts.push(alert.user_id);
}
});
}
@d.command("where", "<member:resolvedMember>", {})
@d.permission("can_where")
async whereCmd(msg: Message, args: { member: Member; time?: number; reminder?: string }) {
let member = await resolveMember(this.bot, this.guild, args.member.id);
sendWhere(this.guild, member, msg.channel, `${msg.member.mention} |`);
}
@d.command("vcalert", "<member:resolvedMember> [duration:delay] [reminder:string$]", {
aliases: ["vca"],
})
@d.permission("can_alert")
async vcalertCmd(msg: Message, args: { member: Member; duration?: number; reminder?: string }) {
let time = args.duration || 600000;
let alertTime = moment().add(time, "millisecond");
let body = args.reminder || "None";
this.alerts.add(msg.author.id, args.member.id, msg.channel.id, alertTime.format("YYYY-MM-DD HH:mm:ss"), body);
if (!this.usersWithAlerts.includes(args.member.id)) {
this.usersWithAlerts.push(args.member.id);
}
msg.channel.createMessage(
`If ${args.member.mention} joins or switches VC in the next ${humanizeDuration(time)} i will notify you`,
);
}
@d.command("vcalerts")
@d.permission("can_alert")
async listVcalertCmd(msg: Message) {
const alerts = await this.alerts.getAlertsByRequestorId(msg.member.id);
if (alerts.length === 0) {
this.sendErrorMessage(msg.channel, "You have no active alerts!");
return;
}
alerts.sort(sorter("expires_at"));
const longestNum = (alerts.length + 1).toString().length;
const lines = Array.from(alerts.entries()).map(([i, alert]) => {
const num = i + 1;
const paddedNum = num.toString().padStart(longestNum, " ");
return `\`${paddedNum}.\` \`${alert.expires_at}\` Member: <@!${alert.user_id}> Reminder: \`${alert.body}\``;
});
createChunkedMessage(msg.channel, lines.join("\n"));
}
@d.command("vcalerts delete", "<num:number>", {
aliases: ["vcalerts d"],
})
@d.permission("can_alert")
async deleteVcalertCmd(msg: Message, args: { num: number }) {
const alerts = await this.alerts.getAlertsByRequestorId(msg.member.id);
alerts.sort(sorter("expires_at"));
const lastNum = alerts.length + 1;
if (args.num > lastNum || args.num < 0) {
msg.channel.createMessage(errorMessage("Unknown alert"));
return;
}
const toDelete = alerts[args.num - 1];
await this.alerts.delete(toDelete.id);
msg.channel.createMessage(successMessage("Alert deleted"));
}
@d.event("voiceChannelJoin")
async userJoinedVC(member: Member, channel: Channel) {
if (this.usersWithAlerts.includes(member.id)) {
this.sendAlerts(member.id);
await this.removeUserIDFromActiveAlerts(member.id);
}
}
@d.event("voiceChannelSwitch")
async userSwitchedVC(member: Member, newChannel: Channel, oldChannel: Channel) {
if (this.usersWithAlerts.includes(member.id)) {
this.sendAlerts(member.id);
await this.removeUserIDFromActiveAlerts(member.id);
}
}
@d.event("guildBanAdd")
async onGuildBanAdd(_, user: User) {
const alerts = await this.alerts.getAlertsByUserId(user.id);
alerts.forEach(alert => {
this.alerts.delete(alert.id);
});
}
async sendAlerts(userid: string) {
const triggeredAlerts = await this.alerts.getAlertsByUserId(userid);
const member = await resolveMember(this.bot, this.guild, userid);
triggeredAlerts.forEach(alert => {
let prepend = `<@!${alert.requestor_id}>, an alert requested by you has triggered!\nReminder: \`${
alert.body
}\`\n`;
sendWhere(this.guild, member, <TextableChannel>this.bot.getChannel(alert.channel_id), prepend);
this.alerts.delete(alert.id);
});
}
async removeUserIDFromActiveAlerts(userid: string) {
const index = this.usersWithAlerts.indexOf(userid);
if (index > -1) {
this.usersWithAlerts.splice(index, 1);
}
}
}
export async function sendWhere(guild: Guild, member: Member, channel: TextableChannel, prepend: string) {
let voice = await (<VoiceChannel>guild.channels.get(member.voiceState.channelID));
if (voice == null) {
channel.createMessage(prepend + "That user is not in a channel");
} else {
let invite = await createInvite(voice);
channel.createMessage(
prepend + ` ${member.mention} is in the following channel: ${voice.name} https://${getInviteLink(invite)}`,
);
}
}
export async function createInvite(vc: VoiceChannel) {
let existingInvites = await vc.getInvites();
if (existingInvites.length !== 0) {
return existingInvites[0];
} else {
return vc.createInvite(undefined);
}
}

View file

@ -24,6 +24,7 @@ import { CustomEventsPlugin } from "./CustomEvents";
import { GuildInfoSaverPlugin } from "./GuildInfoSaver";
import { LogServerPlugin } from "./LogServer";
import { CompanionChannelPlugin } from "./CompanionChannels";
import { LocatePlugin } from "./LocateUser";
/**
* Plugins available to be loaded for individual guilds
@ -52,6 +53,7 @@ export const availablePlugins = [
CustomEventsPlugin,
GuildInfoSaverPlugin,
CompanionChannelPlugin,
LocatePlugin,
];
/**