1
0
mirror of https://github.com/toast-ts/Daggerbot-TS.git synced 2024-11-17 20:30:58 -05:00

Compare commits

...

7 Commits

Author SHA1 Message Date
dependabot[bot]
08d34c9839
Merge 341a8e1156 into 6a237460ed 2024-02-09 22:43:18 +11:00
toast-ts
6a237460ed Change font, container didn't support it. 2024-02-09 22:34:57 +11:00
dependabot[bot]
341a8e1156
Bump sequelize from 6.35.2 to 6.36.0
Bumps [sequelize](https://github.com/sequelize/sequelize) from 6.35.2 to 6.36.0.
- [Release notes](https://github.com/sequelize/sequelize/releases)
- [Commits](https://github.com/sequelize/sequelize/compare/v6.35.2...v6.36.0)

---
updated-dependencies:
- dependency-name: sequelize
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-09 11:28:10 +00:00
toast-ts
b2d2300d13 Drop-in replacement for Canvas 2024-02-09 22:27:08 +11:00
toast-ts
a862564248 Remind myself 2024-02-09 14:59:32 +11:00
toast-ts
a5e45a3b13 Graph optimizations 2024-02-09 14:54:49 +11:00
toast-ts
ab9e88c263 Add raw SQL query support 2024-02-08 07:36:37 +11:00
15 changed files with 250 additions and 2575 deletions

1438
.pnp.cjs generated

File diff suppressed because it is too large Load Diff

View File

@ -32,10 +32,10 @@
"engineStrict": true,
"packageManager": "yarn@4.1.0+sha256.81a00df816059803e6b5148acf03ce313cad36b7f6e5af6efa040a15981a6ffb",
"dependencies": {
"@napi-rs/canvas": "0.1.45",
"@octokit/rest": "20.0.2",
"@toast/tokenservice-client": "1.0.11",
"ansi-colors": "4.1.3",
"canvas": "2.11.2",
"dayjs": "1.11.10",
"discord.js": "14.14.1",
"fast-xml-parser": "4.3.4",
@ -44,7 +44,7 @@
"pg": "8.11.3",
"pg-hstore": "2.3.4",
"redis": "4.6.12",
"sequelize": "6.35.2",
"sequelize": "6.36.0",
"simple-git": "3.22.0",
"systeminformation": "5.21.24",
"undici": "6.6.0"

View File

@ -131,6 +131,7 @@ export default class Developer {
client.users.cache.get(member.id).send(`${message}\n╰ ${interaction.member.displayName}`).then(()=>int.edit(`Successfully sent a DM to **${member.user.username}** with the following message:\n\`\`\`${message}\`\`\``)).catch((e:Error)=>int.edit(`\`${e.message}\``))
},
modify_rank_msgs: async()=>{
if (interaction.guildId !== client.config.dcServer.id) return interaction.reply({content: 'This command is only available in the main server.', ephemeral: true});
const member = interaction.options.getMember('member');
const messages = interaction.options.getInteger('new-message-count');
const oldData = await client.userLevels.fetchUser(member.id);
@ -141,7 +142,6 @@ export default class Developer {
`Successfully modified the message count of **${member.displayName}**`,
`╰ Old: **${oldData.dataValues.messages.toLocaleString('en-US')}**`,
`╰ New: **${newData.messages.toLocaleString('en-US')}**`,
`╰ Difference: **${(newData.messages - oldData.dataValues.messages).toLocaleString('en-US')}**`,
'Although if you set the number too high or low, it will have a bigger impact on the leaderboard graph.'
))
]})

View File

@ -62,7 +62,7 @@ export default class MP {
.setImage(`attachment://${attachmentName}`)
.setAuthor({name: `${DSS.slots.used}/${DSS.slots.capacity}`})
.setFooter({text: `Current time: ${('0'+Math.floor((DSS?.server.dayTime/3600/1000))).slice(-2)}:${('0'+Math.floor((DSS?.server.dayTime/60/1000)%60)).slice(-2)}`})
], files: [new client.attachment(canvas.toBuffer(), {name: attachmentName})]})
], files: [new client.attachment(canvas.toBuffer('image/jpeg'), {name: attachmentName})]})
},
details: async()=>{
const DSS = await fetchData(client, interaction, choiceSelector) as FSData;

View File

@ -42,7 +42,7 @@ export default class Rank {
name: 'Top users sorted by messages sent:',
value: allData.sort((a,b)=>b.messages - a.messages).slice(0,15).map((x,i)=>`${i+1}. <@${x.dataValues.id}>: ${x.messages.toLocaleString('en-US')}`).join('\n')
}).setImage('attachment://dailyMessages.jpg').setFooter({text: 'Graph updates daily'})],
files: [new client.attachment(graph.toBuffer(), {name: 'dailyMessages.jpg'})]
files: [new client.attachment(graph.toBuffer('image/jpeg'), {name: 'dailyMessages.jpg'})]
})
},
notification: async()=>{

View File

@ -1,10 +1,20 @@
import {createCanvas, Canvas, CanvasRenderingContext2D} from 'canvas';
import {createCanvas, Canvas, SKRSContext2D} from '@napi-rs/canvas';
import {Config} from 'src/interfaces';
import ConfigHelper from '../helpers/ConfigHelper.js';
export default class CanvasBuilder {
private canvas: Canvas;
private ctx: CanvasRenderingContext2D;
private config: Config;
private readonly canvas: Canvas;
private readonly ctx: SKRSContext2D;
private readonly config: Config;
private readonly palette = {
// Color palette for the graph -- The variables are named exactly what it shows in graph to make it easier to be referenced to.
oddHorizontal: '#555B63',
evenHorizontal: '#3E4245',
background: '#111111',
textColor: '#FFFFFF',
redLine: '#E62C3B',
yellowLine: '#FFEA00',
greenLine: '#57F287'
};
constructor() {
this.canvas = createCanvas(1500, 750);
@ -13,20 +23,11 @@ export default class CanvasBuilder {
}
public async generateGraph(data:number[], type:'players'|'leaderboard'):Promise<Canvas> {
// Color layout for the graph -- The variables are named exactly what it shows in graph to make it easier to be referenced to.
let oddHorizontal = '#555B63';
let evenHorizontal = '#3E4245';
let background = '#111111';
let textColor = '#FFFFFF';
let redLine = '#E62C3B';
let yellowLine = '#FFEA00';
let greenLine = '#57F287';
// Handle negative
for (const [i, change] of data.entries()) if (change as number < 0) data[i] = data[i - 1] || data[i + 1] || 0;
for (const [i, change] of data.entries()) if (change < 0) data[i] = data[i - 1] || data[i + 1] || 0;
const LBdataFirst = Math.ceil(Math.max(...data) * 10 ** (-Math.max(...data).toString().split('').length + 1)) * 10 ** (Math.max(...data).toString().split('').length - 1)
const LBdataSecond = Math.ceil(Math.max(...data) * 10 ** (-Math.max(...data).toString().split('').length + 2)) * 10 ** (Math.max(...data).toString().split('').length - 2)
const LBdataFirst = Math.ceil(Math.max(...data) * 10 ** (-Math.max(...data).toString().split('').length + 2)) * 10 ** (Math.max(...data).toString().split('').length - 2)
const LBdataSecond = Math.ceil(Math.max(...data) * 10 ** (-Math.max(...data).toString().split('').length + 3)) * 10 ** (Math.max(...data).toString().split('').length - 3)
const firstTop = type === 'leaderboard' ? LBdataFirst : 16;
const secondTop = type === 'leaderboard' ? LBdataSecond : 16;
@ -34,7 +35,7 @@ export default class CanvasBuilder {
const origin = [15, 65];
const size = [1300, 630];
const nodeWidth = size[0] / (data.length - 1);
this.ctx.fillStyle = background;
this.ctx.fillStyle = this.palette.background;
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
// Grey horizontal lines
@ -47,33 +48,20 @@ export default class CanvasBuilder {
}
const chosenInterval = intervalCandidates.sort((a,b)=>b[2]-a[2])[0];
let prevY:number[] = [];
this.ctx.strokeStyle = oddHorizontal;
this.ctx.strokeStyle = this.palette.oddHorizontal;
if (type === 'leaderboard') for (let i = 0; i <= chosenInterval[1]; i++) {
for (let i = 0; i <= chosenInterval[1]; i++) {
const y = origin[1] + size[1] - (i * (chosenInterval[0] / secondTop) * size[1]);
if (y < origin[1]) continue;
const even = ((i + 1) % 2) === 0;
if (even) this.ctx.strokeStyle = evenHorizontal;
if (even) this.ctx.strokeStyle = this.palette.evenHorizontal;
this.ctx.beginPath();
this.ctx.lineTo(origin[0], y);
this.ctx.lineTo(origin[0] + size[0], y);
this.ctx.stroke();
this.ctx.closePath();
if (even) this.ctx.strokeStyle = oddHorizontal;
prevY = [y, i * chosenInterval[0]];
}
else for (let i = 0; i < data.length; i++) {
const y = origin[1] + size[1] - (i * (chosenInterval[0] / secondTop) * size[1]);
if (y < origin[1]) continue;
const even = ((i + 1) % 2) === 0;
if (even) this.ctx.strokeStyle = evenHorizontal;
this.ctx.beginPath();
this.ctx.lineTo(origin[0], y);
this.ctx.lineTo(origin[0] + size[0], y);
this.ctx.stroke();
this.ctx.closePath();
if (even) this.ctx.strokeStyle = oddHorizontal;
prevY.push(y, i * chosenInterval[0]);
if (even) this.ctx.strokeStyle = this.palette.oddHorizontal;
prevY.push(y, i * chosenInterval[0]); // It didn't seem to take effect when I tested on leaderboard, so using push instead for both players and leaderboard.
}
// 30 day/minute mark
@ -87,15 +75,14 @@ export default class CanvasBuilder {
this.ctx.setLineDash([]);
// Draw points
const isLeaderboard =()=>type === 'leaderboard' ? this.config.embedColor as string : null;
this.ctx.strokeStyle = isLeaderboard();
this.ctx.fillStyle = isLeaderboard();
this.ctx.strokeStyle = type === 'leaderboard' ? this.config.embedColor as string : null;
this.ctx.fillStyle = type === 'leaderboard' ? this.config.embedColor as string : null;
this.ctx.lineWidth = 5;
const gradient = this.ctx.createLinearGradient(0, origin[1], 0, origin[1] + size[1]);
gradient.addColorStop(1 / 16, redLine);
gradient.addColorStop(5 / 16, yellowLine);
gradient.addColorStop(12 / 16, greenLine);
gradient.addColorStop(1 / 16, this.palette.redLine);
gradient.addColorStop(5 / 16, this.palette.yellowLine);
gradient.addColorStop(12 / 16, this.palette.greenLine);
let lastCoordinates:number[] = [];
for (let [i, currentValue] of data.entries()) {
@ -132,8 +119,8 @@ export default class CanvasBuilder {
}
// Draw text
this.ctx.font = '400 ' + textSize + 'px sans-serif';
this.ctx.fillStyle = textColor;
this.ctx.font = `400 ${textSize}px DejaVu Sans`;
this.ctx.fillStyle = this.palette.textColor;
// Highest value
this.ctx.fillText(type === 'leaderboard'

View File

@ -55,6 +55,7 @@ export class MPServerSvc {
})
this.model.sync();
}
query = async(pattern:string)=>await this.model.sequelize.query(pattern);
async fetchPlayerData(serverName:string) {
const findServerByName = await this.model.findOne({where: {serverName: serverName}});
if (findServerByName) return findServerByName.dataValues.playerData;

View File

@ -30,6 +30,7 @@ export class DailyMsgsSvc {
})
this.model.sync();
}
query = async(pattern:string)=>await this.model.sequelize.query(pattern);
nukeDays = async()=>await this.model.destroy({truncate: true});
fetchDays = async()=>await this.model.findAll();
async newDay(formattedDate:number, total:number) {

View File

@ -25,6 +25,7 @@ export class ProhibitedWordsSvc {
})
this.model.sync();
}
query = async(pattern:string)=>await this.model.sequelize.query(pattern);
findWord = async(word:string)=>await this.model.findByPk(word);
getAllWords = async()=>await this.model.findAll();
insertWord = async(word:string)=>await this.model.create({word: word});

View File

@ -83,6 +83,7 @@ export class PunishmentsSvc {
});
this.model.sync();
}
query = async(pattern:string)=>await this.model.sequelize.query(pattern);
async updateReason(caseId:number, reason:string) {
const findCase = this.findCase(caseId);
if (findCase) return this.model.update({reason: reason}, {where: {case_id: caseId}});

View File

@ -40,6 +40,7 @@ export class SuggestionsSvc {
})
this.model.sync();
}
query = async(pattern:string)=>await this.model.sequelize.query(pattern);
fetchById = async(id:number)=>await this.model.findByPk(id);
updateStatus = async(id:number, status:string)=>await this.model.update({status: status}, {where: {id: id}});
create =(userid:string, description:string)=>this.model.create({userid: userid, suggestion: description, status: 'Pending'})

View File

@ -50,6 +50,7 @@ export class TagSystemSvc {
});
this.model.sync();
}
query = async(pattern:string)=>await this.model.sequelize.query(pattern);
async createTag(userid:string, tagName:string, message:string, embedFlag:boolean) {
CacheServer.delete('tags');
return await this.model.create({userid: userid, tagname: tagName, message: message.replace(/\\n/g, '\n'), embedFlag: embedFlag});

View File

@ -57,6 +57,7 @@ export class UserLevelsSvc {
});
this.model.sync();
}
query = async(pattern:string)=>await this.model.sequelize.query(pattern);
fetchEveryone = async()=>await this.model.findAll();
fetchUser = async(userId:string)=>await this.model.findByPk(userId);
deleteUser = async(userId:string)=>await this.model.destroy({where: {id: userId}});

View File

@ -34,6 +34,7 @@ export class YouTubeChannelsSvc {
})
this.model.sync();
}
query = async(pattern:string)=>await this.model.sequelize.query(pattern);
async addChannel(YTChannelID:string, DCChannelID:string, DCRole:string) {
if (await this.model.findOne({where: {ytchannel: YTChannelID}})) return false;
await this.model.create({ytchannel: YTChannelID, dcchannel: DCChannelID, dcrole: DCRole});

1296
yarn.lock

File diff suppressed because it is too large Load Diff