mirror of
https://github.com/citra-emu/discord-bot.git
synced 2025-08-28 17:41:02 +00:00
Merge branch 'citra-emu:master' into master
This commit is contained in:
commit
515591c680
1
env.json
1
env.json
|
@ -33,6 +33,7 @@
|
||||||
"description": "The unique ID for the role that the bot will *remove* when the user accepts the rules."
|
"description": "The unique ID for the role that the bot will *remove* when the user accepts the rules."
|
||||||
},
|
},
|
||||||
"DISCORD_DEVELOPER_ROLE": true,
|
"DISCORD_DEVELOPER_ROLE": true,
|
||||||
|
"DISCORD_TESTER_ROLE": true,
|
||||||
"DISCORD_LOGIN_TOKEN": {
|
"DISCORD_LOGIN_TOKEN": {
|
||||||
"description": "The login token of the bot."
|
"description": "The login token of the bot."
|
||||||
},
|
},
|
||||||
|
|
21
package.json
21
package.json
|
@ -12,35 +12,34 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"checkenv": "^1.2.2",
|
"checkenv": "^1.2.2",
|
||||||
"discord.js": "^14.7.1",
|
"discord.js": "^14.9.0",
|
||||||
"ip": "^1.1.8",
|
"ip": "^1.1.8",
|
||||||
"logdna": "^3.5.3",
|
"logdna": "^3.5.3",
|
||||||
"logdna-winston": "^4.0.1",
|
"logdna-winston": "^4.0.1",
|
||||||
"node-fetch": "^3",
|
"node-fetch": "^3",
|
||||||
"string-similarity": "^4.0.4",
|
"string-similarity": "^4.0.4",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^5.0.4",
|
||||||
"winston": "^3.8.2"
|
"winston": "^3.8.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tsconfig/node18": "^1.0.1",
|
"@tsconfig/node18": "^2.0.0",
|
||||||
"@types/ip": "^1.1.0",
|
"@types/ip": "^1.1.0",
|
||||||
"@types/node": "^18.11.18",
|
"@types/node": "^18.16.2",
|
||||||
"@types/node-fetch": "^2",
|
|
||||||
"@types/string-similarity": "^4.0.0",
|
"@types/string-similarity": "^4.0.0",
|
||||||
"@types/ws": "^8.5.4",
|
"@types/ws": "^8.5.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.49.0",
|
"@typescript-eslint/eslint-plugin": "^5.59.1",
|
||||||
"@typescript-eslint/parser": "^5.49.0",
|
"@typescript-eslint/parser": "^5.59.1",
|
||||||
"esbuild": "^0.17.5",
|
"esbuild": "^0.17.18",
|
||||||
"eslint": "^8.32.0",
|
"eslint": "^8.39.0",
|
||||||
"eslint-config-standard": "^17.0.0",
|
"eslint-config-standard": "^17.0.0",
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-n": "^15.6.1",
|
"eslint-plugin-n": "^15.7.0",
|
||||||
"eslint-plugin-promise": "^6.1.1",
|
"eslint-plugin-promise": "^6.1.1",
|
||||||
"ts-node": "^10.9.1"
|
"ts-node": "^10.9.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "node generateExports.js",
|
"postinstall": "node generateExports.js",
|
||||||
"build": "yarn run esbuild --bundle src/server.ts --platform=node --target=node18 --outdir=dist/",
|
"build": "yarn run esbuild --bundle src/server.ts --platform=node --target=node18 --outdir=dist/ --minify-whitespace",
|
||||||
"check": "yarn run tsc --noEmit",
|
"check": "yarn run tsc --noEmit",
|
||||||
"bundle": "./bundle.sh",
|
"bundle": "./bundle.sh",
|
||||||
"serve": "yarn run ts-node ./src/server.ts"
|
"serve": "yarn run ts-node ./src/server.ts"
|
||||||
|
|
|
@ -3,7 +3,5 @@ import * as discord from 'discord.js';
|
||||||
|
|
||||||
export const roles = ['Admins', 'Moderators', 'CitraBot'];
|
export const roles = ['Admins', 'Moderators', 'CitraBot'];
|
||||||
export async function command (message: discord.Message) {
|
export async function command (message: discord.Message) {
|
||||||
return Promise.all(message.mentions.users.map(async (user) => {
|
return Promise.all(message.mentions.users.map(async (user) => ban(user, message.author, message.guild)));
|
||||||
await ban(user, message.author, message.guild);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ const compatStrings: ICompatList = {
|
||||||
99: { key: '99', name: 'Not Tested', color: 'DarkButNotBlack', description: 'The game has not yet been tested.' }
|
99: { key: '99', name: 'Not Tested', color: 'DarkButNotBlack', description: 'The game has not yet been tested.' }
|
||||||
};
|
};
|
||||||
|
|
||||||
async function updateDatabase() {
|
async function updateDatabase () {
|
||||||
let body: any;
|
let body: IGameDBEntry[];
|
||||||
if (!targetServer) {
|
if (!targetServer) {
|
||||||
logger.error('Unable to download latest games list!');
|
logger.error('Unable to download latest games list!');
|
||||||
return;
|
return;
|
||||||
|
@ -30,7 +30,7 @@ async function updateDatabase() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(targetServer);
|
const response = await fetch(targetServer);
|
||||||
body = await response.json();
|
body = (await response.json()) as IGameDBEntry[];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Unable to download latest games list!');
|
logger.error('Unable to download latest games list!');
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -50,7 +50,7 @@ async function updateDatabase() {
|
||||||
state.gameDBPromise = null;
|
state.gameDBPromise = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function command(message: discord.Message) {
|
export async function command (message: discord.Message) {
|
||||||
if (Date.now() - state.lastGameDBUpdate > refreshTime) {
|
if (Date.now() - state.lastGameDBUpdate > refreshTime) {
|
||||||
// Update remote list of games locally.
|
// Update remote list of games locally.
|
||||||
const waitMessage = message.channel.send('This will take a second...');
|
const waitMessage = message.channel.send('This will take a second...');
|
||||||
|
@ -87,8 +87,7 @@ export async function command(message: discord.Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bestGame) {
|
if (!bestGame) {
|
||||||
await message.channel.send('Game could not be found.');
|
return message.channel.send('Game could not be found.');
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const screenshot = `${iconBase}${bestGame.directory}.png`;
|
const screenshot = `${iconBase}${bestGame.directory}.png`;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import state from '../state';
|
|
||||||
import logger from '../logging';
|
import logger from '../logging';
|
||||||
import * as discord from 'discord.js';
|
import * as discord from 'discord.js';
|
||||||
|
import { grantRole } from '../common';
|
||||||
|
|
||||||
export const roles = ['Admins', 'Moderators', 'CitraBot'];
|
export const roles = ['Admins', 'Moderators', 'CitraBot'];
|
||||||
export async function command (message: discord.Message) {
|
export async function command (message: discord.Message) {
|
||||||
|
@ -12,26 +12,9 @@ export async function command (message: discord.Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(message.mentions.users.map(async (user) => {
|
return Promise.all(message.mentions.users.map(async (user) => {
|
||||||
return message.guild?.members.fetch(user).then((member) => {
|
return message.guild?.members.fetch(user).then((member) => grantRole(member, role, message.channel))
|
||||||
const alreadyJoined = member.roles.cache.has(role);
|
.catch(async () => {
|
||||||
|
await message.channel.send(`User ${user.toString()} was not found in the channel.`);
|
||||||
if (alreadyJoined) {
|
});
|
||||||
member.roles.remove(role).then(async () => {
|
|
||||||
await message.channel.send(`${user.toString()}'s speech has been revoked in the #development channel.`);
|
|
||||||
}).catch(async () => {
|
|
||||||
await state.logChannel?.send(`Error revoking ${user.toString()}'s developer speech...`);
|
|
||||||
logger.error(`Error revoking ${user.toString()} ${user.username}'s developer speech...`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
member.roles.add(role).then(async () => {
|
|
||||||
await message.channel.send(`${user.toString()} has been granted speech in the #development channel.`);
|
|
||||||
}).catch(async () => {
|
|
||||||
await state.logChannel?.send(`Error granting ${user.toString()}'s developer speech...`);
|
|
||||||
logger.error(`Error granting ${user.toString()} ${user.username}'s developer speech...`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch(async () => {
|
|
||||||
await message.channel.send(`User ${user.toString()} was not found in the channel.`);
|
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
20
src/commands/grantTester.ts
Normal file
20
src/commands/grantTester.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import logger from '../logging';
|
||||||
|
import * as discord from 'discord.js';
|
||||||
|
import { grantRole } from '../common';
|
||||||
|
|
||||||
|
const role = process.env.DISCORD_TESTER_ROLE;
|
||||||
|
|
||||||
|
export const roles = ['Admins', 'Moderators', 'CitraBot'];
|
||||||
|
export async function command (message: discord.Message) {
|
||||||
|
if (!role) {
|
||||||
|
logger.error('DISCORD_TESTER_ROLE suddenly became undefined?!');
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(message.mentions.users.map(async (user) => {
|
||||||
|
return message.guild?.members.fetch(user).then((member) => grantRole(member, role, message.channel))
|
||||||
|
.catch(async () => {
|
||||||
|
await message.channel.send(`User ${user.toString()} was not found in the channel.`);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ export async function command (message: discord.Message, reply: string | undefin
|
||||||
if (reply == null) {
|
if (reply == null) {
|
||||||
replyMessage = message.content.substring(message.content.indexOf(' ') + 1);
|
replyMessage = message.content.substring(message.content.indexOf(' ') + 1);
|
||||||
} else {
|
} else {
|
||||||
replyMessage = `${message.mentions.users.map(user => `${user.toString()}`).join(' ')} ${reply}`;
|
replyMessage = `${message.mentions.users.map(user => user.toString()).join(' ')} ${reply}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
await message.channel.send(replyMessage);
|
await message.channel.send(replyMessage);
|
||||||
|
|
|
@ -7,17 +7,17 @@ const fetchOptions = {
|
||||||
const repo = process.env.GITHUB_REPOSITORY || 'citra-emu/citra';
|
const repo = process.env.GITHUB_REPOSITORY || 'citra-emu/citra';
|
||||||
|
|
||||||
export const roles = ['Admins', 'Moderators', 'Developer'];
|
export const roles = ['Admins', 'Moderators', 'Developer'];
|
||||||
export async function command(message: discord.Message) {
|
export async function command (message: discord.Message) {
|
||||||
const prNumber = message.content.substring(message.content.indexOf(' ') + 1).replace(/\n/g, '');
|
const prNumber = message.content.substring(message.content.indexOf(' ') + 1).replace(/\n/g, '');
|
||||||
const url = `https://api.github.com/repos/${repo}/pulls/${prNumber}`;
|
const url = `https://api.github.com/repos/${repo}/pulls/${prNumber}`;
|
||||||
return fetch(url, fetchOptions).then(response => response.json()).then((pr: any) => {
|
return fetch(url, fetchOptions).then(response => response.json()).then(async (pr: any) => {
|
||||||
if (!pr || pr.documentation_url || !pr.head) throw new Error('PR not found');
|
if (!pr || pr.documentation_url || !pr.head) throw new Error('PR not found');
|
||||||
const headSHA = pr.head.sha;
|
const headSHA = pr.head.sha;
|
||||||
// use the new GitHub checks API
|
// use the new GitHub checks API
|
||||||
fetch(`https://api.github.com/repos/${repo}/commits/${headSHA}/check-runs`, fetchOptions).then(response => response.json()).then(async (statuses: any) => {
|
return fetch(`https://api.github.com/repos/${repo}/commits/${headSHA}/check-runs`, fetchOptions).then(response => response.json()).then(async (statuses: any) => {
|
||||||
if (!statuses.check_runs || statuses.total_count < 1) throw new Error('No check runs');
|
if (!statuses.check_runs || statuses.total_count < 1) throw new Error('No check runs');
|
||||||
const msg = new discord.EmbedBuilder().setTitle(`Status for PR #${prNumber}`).setURL(pr.html_url);
|
const msg = new discord.EmbedBuilder().setTitle(`Status for PR #${prNumber}`).setURL(pr.html_url);
|
||||||
let color = 'GREEN' as discord.ColorResolvable;
|
let color: discord.ColorResolvable = 'Green';
|
||||||
statuses.check_runs.forEach((run: any) => {
|
statuses.check_runs.forEach((run: any) => {
|
||||||
msg.addFields({ name: run.name, value: `**[${run.status} ${run.conclusion}](${run.html_url})**` });
|
msg.addFields({ name: run.name, value: `**[${run.status} ${run.conclusion}](${run.html_url})**` });
|
||||||
if (run.conclusion !== 'success') color = 'Red';
|
if (run.conclusion !== 'success') color = 'Red';
|
||||||
|
|
|
@ -5,7 +5,7 @@ import UserWarning from '../models/UserWarning';
|
||||||
import * as discord from 'discord.js';
|
import * as discord from 'discord.js';
|
||||||
|
|
||||||
export const roles = ['Admins', 'Moderators'];
|
export const roles = ['Admins', 'Moderators'];
|
||||||
export async function command(message: discord.Message) {
|
export async function command (message: discord.Message) {
|
||||||
const silent = message.content.includes('silent');
|
const silent = message.content.includes('silent');
|
||||||
|
|
||||||
return Promise.all(message.mentions.users.map(async (user) => {
|
return Promise.all(message.mentions.users.map(async (user) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import state from '../state';
|
import state from '../state';
|
||||||
import * as discord from 'discord.js';
|
import * as discord from 'discord.js';
|
||||||
|
|
||||||
export async function command(message: discord.Message) {
|
export async function command (message: discord.Message) {
|
||||||
return Promise.all(message.mentions.users.map(async (user) => {
|
return Promise.all(message.mentions.users.map(async (user) => {
|
||||||
const warnings = state.warnings.filter(x => x.id === user.id && !x.cleared);
|
const warnings = state.warnings.filter(x => x.id === user.id && !x.cleared);
|
||||||
await message.channel.send(`${user.toString()}, you have ${warnings.length} total warnings.`);
|
await message.channel.send(`${user.toString()}, you have ${warnings.length} total warnings.`);
|
||||||
|
|
|
@ -18,3 +18,26 @@ export async function ban (user: discord.User, moderator: discord.User, guild: d
|
||||||
|
|
||||||
data.flushBans();
|
data.flushBans();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function grantRole (member: discord.GuildMember, role: string, channel: discord.TextBasedChannel) {
|
||||||
|
const user = member.user;
|
||||||
|
const roleDisplayName = role.toLowerCase();
|
||||||
|
|
||||||
|
const alreadyJoined = member.roles.cache.has(role);
|
||||||
|
if (alreadyJoined) {
|
||||||
|
member.roles.remove(role).then(async () => {
|
||||||
|
await channel.send(`${user.toString()}'s ${roleDisplayName} role has been revoked.`);
|
||||||
|
}).catch(async () => {
|
||||||
|
await state.logChannel?.send(`Error revoking ${user.toString()}'s ${roleDisplayName} speech...`);
|
||||||
|
logger.error(`Error revoking ${user.toString()} ${user.username}'s ${roleDisplayName} speech...`);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
member.roles.add(role).then(async () => {
|
||||||
|
await channel.send(`${user.toString()} has been granted ${roleDisplayName} speech.`);
|
||||||
|
}).catch(async () => {
|
||||||
|
await state.logChannel?.send(`Error granting ${user.toString()}'s ${roleDisplayName} speech...`);
|
||||||
|
logger.error(`Error granting ${user.toString()} ${user.username}'s ${roleDisplayName} speech...`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"compat": { "reply": "Click here to view our game compatibility list: <https://citra-emu.org/game/>. ***A Reminder***: Compatibility ratings are user submitted data and may not accurately reflect the game's playability. Your experience may or may not be the same due to differences in hardware or software environments."},
|
"compat": { "reply": "Click here to view our game compatibility list: <https://citra-emu.org/game/>. ***A Reminder***: Compatibility ratings are user submitted data and may not accurately reflect the game's playability. Your experience may or may not be the same due to differences in hardware or software environments."},
|
||||||
"updates": { "reply": "You can check our latest updates on *Github*. <https://github.com/citra-emu/citra/pulse>"},
|
"updates": { "reply": "You can check our latest updates on *Github*. <https://github.com/citra-emu/citra/pulse>"},
|
||||||
"download": { "reply": "Please only download from the official *Citra* website, as downloading from other sources is not supported here. <https://citra-emu.org/download/>"},
|
"download": { "reply": "Please only download from the official *Citra* website, as downloading from other sources is not supported here. <https://citra-emu.org/download/>"},
|
||||||
"legal": { "reply": "*Citra* is legal, we don't support illegal activities. Dumping your purchased games and system files from your 3DS is legal. Downloading them is not."},
|
"legal": { "reply": "*Citra* is legal, we don't support illegal activities. Dumping your purchased games from your 3DS is legal. Downloading them is not."},
|
||||||
"building": { "reply": "Please refer to our __building guides__.\nWindows: <https://citra-emu.org/wiki/building-for-windows> \nmacOS: <https://citra-emu.org/wiki/building-for-macos> \nLinux: <https://citra-emu.org/wiki/building-for-linux>"},
|
"building": { "reply": "Please refer to our __building guides__.\nWindows: <https://citra-emu.org/wiki/building-for-windows> \nmacOS: <https://citra-emu.org/wiki/building-for-macos> \nLinux: <https://citra-emu.org/wiki/building-for-linux>"},
|
||||||
"log": { "reply": "For assistance with your issue, please accurately describe the problem and post a log file. The following guide shows how to __get the log file__: <https://community.citra-emu.org/t/how-to-upload-the-log-file/296>"},
|
"log": { "reply": "For assistance with your issue, please accurately describe the problem and post a log file. The following guide shows how to __get the log file__: <https://community.citra-emu.org/t/how-to-upload-the-log-file/296>"},
|
||||||
"canary": { "reply": "The Nightly build of Citra contains already reviewed and tested features. If you require support with the installation or use of Citra, or you want to report bugs you should use this version.\n\nThe Canary build of Citra is the same as our Nightly builds, with additional features that are still waiting on review before making it into the official Citra builds. We will not provide support for issues found only in this version. If you believe you’ve found a bug, please retest on our Nightly builds. Both versions are still in development, so expect crashes and bugs."},
|
"canary": { "reply": "The Nightly build of Citra contains already reviewed and tested features. If you require support with the installation or use of Citra, or you want to report bugs you should use this version.\n\nThe Canary build of Citra is the same as our Nightly builds, with additional features that are still waiting on review before making it into the official Citra builds. We will not provide support for issues found only in this version. If you believe you’ve found a bug, please retest on our Nightly builds. Both versions are still in development, so expect crashes and bugs."},
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
"portable": {"reply": "Go to <https://citra-emu.org/download/> and select `Manual download`. Then under **Nightly Build**, click on your operating system's icon to the right of the latest build available to download the build.\nExtract it (.7z can be extracted using Winrar or 7zip) and put it wherever you wish. Inside the extracted `nightly-mingw` folder, create a folder called `user`. This Citra should now store all of its config, save files and such inside of this `user` folder.\nCheck to make sure that this `user` folder is in the same folder that contains `citra-qt(.exe)`\nNow run the `citra-qt` executable found inside of the `mingw` folder."},
|
"portable": {"reply": "Go to <https://citra-emu.org/download/> and select `Manual download`. Then under **Nightly Build**, click on your operating system's icon to the right of the latest build available to download the build.\nExtract it (.7z can be extracted using Winrar or 7zip) and put it wherever you wish. Inside the extracted `nightly-mingw` folder, create a folder called `user`. This Citra should now store all of its config, save files and such inside of this `user` folder.\nCheck to make sure that this `user` folder is in the same folder that contains `citra-qt(.exe)`\nNow run the `citra-qt` executable found inside of the `mingw` folder."},
|
||||||
"ios": {"reply": "Citra does not have an iOS version because iOS is a \"funky\" operating system to develop for. Therefore, any related videos are scams, and any links are most likely viruses."},
|
"ios": {"reply": "Citra does not have an iOS version because iOS is a \"funky\" operating system to develop for. Therefore, any related videos are scams, and any links are most likely viruses."},
|
||||||
"macos": {"reply": "macOS support has been temporarily dropped whilst work on the graphics backend is underway. Please download the last working build for macOS:\n\nDownload `citra-osx-20220901-d380980.tar.gz` from <https://github.com/citra-emu/citra-nightly/releases/download/nightly-1782/citra-osx-20220901-d380980.tar.gz>\nExtract the `.tar.gz` file then run `citra-qt`."},
|
"macos": {"reply": "macOS support has been temporarily dropped whilst work on the graphics backend is underway. Please download the last working build for macOS:\n\nDownload `citra-osx-20220901-d380980.tar.gz` from <https://github.com/citra-emu/citra-nightly/releases/download/nightly-1782/citra-osx-20220901-d380980.tar.gz>\nExtract the `.tar.gz` file then run `citra-qt`."},
|
||||||
"piracy": {"reply": "*Citra* is legal, we don't support illegal activities. Dumping your purchased games and system files from your 3DS is legal. Downloading them is not.\n\nRefer to our __game dumping guides__. \nFor Cartridges: <https://citra-emu.org/wiki/dumping-game-cartridges/> \nFor Installed Titles: <https://citra-emu.org/wiki/dumping-installed-titles/> \nTo dump DLC and Updates, use this guide <https://citra-emu.org/wiki/dumping-updates-and-dlcs/> and install the results through `File -> Install CIA...`\n\nAlso, please refresh yourself on the <#417321837916192779> you agreed to when you joined this server."},
|
"piracy": {"reply": "*Citra* is legal, we don't support illegal activities. Dumping your purchased games from your 3DS is legal. Downloading them is not.\n\nRefer to our __game dumping guides__. \nFor Cartridges: <https://citra-emu.org/wiki/dumping-game-cartridges/> \nFor Installed Titles: <https://citra-emu.org/wiki/dumping-installed-titles/> \nTo dump DLC and Updates, use this guide <https://citra-emu.org/wiki/dumping-updates-and-dlcs/> and install the results through `File -> Install CIA...`\n\nAlso, please refresh yourself on the <#417321837916192779> you agreed to when you joined this server."},
|
||||||
"saves": {"reply": "Download Checkpoint and open it on the 3DS. Select the game you want, click L. If you require extdata too, not all games do, press X then press L.\n\nThese will be dumped to /3ds/Checkpoint/saves then either saves or extdata.\n\nLaunch Citra and make sure your game directory is listed on the main screen so the game shows up there. Right click on the game you want then choose Open Save Data Location or Open Extra Data Location. Make sure to launch the game at least once in Citra to create these folders first. \n\nOnce those have been open, just replace any save files in Citra with the ones dumped from your 3DS.\n<https://github.com/FlagBrew/Checkpoint>\nTo reverse this and put a Citra save on the 3DS, work backwards and use R to restore it."},
|
"saves": {"reply": "Download Checkpoint and open it on the 3DS. Select the game you want, click L. If you require extdata too, not all games do, press X then press L.\n\nThese will be dumped to /3ds/Checkpoint/saves then either saves or extdata.\n\nLaunch Citra and make sure your game directory is listed on the main screen so the game shows up there. Right click on the game you want then choose Open Save Data Location or Open Extra Data Location. Make sure to launch the game at least once in Citra to create these folders first. \n\nOnce those have been open, just replace any save files in Citra with the ones dumped from your 3DS.\n<https://github.com/FlagBrew/Checkpoint>\nTo reverse this and put a Citra save on the 3DS, work backwards and use R to restore it."},
|
||||||
"states": {"reply": "Citra has two kinds of saves available to users, in-game saves and save states.\n\nIn-game saves are the ones you know from the 3DS. These can be shared between devices and are recommended for general use, as they do not corrupt as easily.\nSave states, on the other hand, save Citra's entire emulation state. This includes Citra's configuration, a game's RNG seed, as well as any faults in the emulation at the time of saving. This makes them very useful as a tool for practicing in-game tricks, or for usage in shiny hunting and other RNG related trigger events. However they're not suitable as replacements for in-game save files as the faults in the emulation state would keep building up until the emulation state is too unstable to load properly. They're also ***non-transferable*** because they are made with one setup and only one."},
|
"states": {"reply": "Citra has two kinds of saves available to users, in-game saves and save states.\n\nIn-game saves are the ones you know from the 3DS. These can be shared between devices and are recommended for general use, as they do not corrupt as easily.\nSave states, on the other hand, save Citra's entire emulation state. This includes Citra's configuration, a game's RNG seed, as well as any faults in the emulation at the time of saving. This makes them very useful as a tool for practicing in-game tricks, or for usage in shiny hunting and other RNG related trigger events. However they're not suitable as replacements for in-game save files as the faults in the emulation state would keep building up until the emulation state is too unstable to load properly. They're also ***non-transferable*** because they are made with one setup and only one."},
|
||||||
"folder": {"reply": "When you open the game selector, you choose the folder your games are in, not the games themselves. Those will auto-populate."},
|
"folder": {"reply": "When you open the game selector, you choose the folder your games are in, not the games themselves. Those will auto-populate."},
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"lenny": { "reply": "( ͡° ͜ʖ ͡°)"},
|
"lenny": { "reply": "( ͡° ͜ʖ ͡°)"},
|
||||||
"( ͡° ͜ʖ ͡°)": { "reply": "lenny"},
|
"( ͡° ͜ʖ ͡°)": { "reply": "lenny"},
|
||||||
"format": { "reply": "A full description of game formats the yuzu supports and when to use them can be found on our wiki. <https://yuzu-emu.org/wiki/overview-of-switch-game-formats/>"},
|
"format": { "reply": "A full description of game formats the yuzu supports and when to use them can be found on our wiki. <https://yuzu-emu.org/wiki/overview-of-switch-game-formats/>"},
|
||||||
"keys": { "reply": "Most games require encryption keys to boot. You can dump them from your Switch by following this guide. <https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys>"},
|
"keys": { "reply": "Most games require encryption keys to boot. You can dump them from your Switch by following this guide. <https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys>"},
|
||||||
"game-updates": { "reply": "Installing and using game updates are a separate process from the base game. Check out our updates tutorial on our wiki. <https://yuzu-emu.org/wiki/how-to-install-and-use-game-updates/>"},
|
"game-updates": { "reply": "Installing and using game updates are a separate process from the base game. Check out our updates tutorial on our wiki. <https://yuzu-emu.org/wiki/how-to-install-and-use-game-updates/>"},
|
||||||
"appdata": { "reply": "Please refer to the following guide to fully reinstall yuzu: <https://yuzu-emu.org/wiki/faq/#yuzu-will-not-update-further-or-starts-with-a-qt-platform-error>"},
|
"appdata": { "reply": "Please refer to the following guide to fully reinstall yuzu: <https://yuzu-emu.org/wiki/faq/#yuzu-will-not-update-further-or-starts-with-a-qt-platform-error>"},
|
||||||
"log": { "reply": "For assistance with your issue, please accurately describe the problem and post a log file. The following guide shows how to __get the log file__: <https://yuzu-emu.org/help/reference/log-files/>"},
|
"log": { "reply": "For assistance with your issue, please accurately describe the problem and post a log file. The following guide shows how to __get the log file__: <https://yuzu-emu.org/help/reference/log-files/>"},
|
||||||
|
@ -41,10 +41,11 @@
|
||||||
"vc": { "reply": "yuzu requires the latest versions of Microsoft Visual C++. Please download and install the following dependency: <https://aka.ms/vs/17/release/vc_redist.x64.exe>"},
|
"vc": { "reply": "yuzu requires the latest versions of Microsoft Visual C++. Please download and install the following dependency: <https://aka.ms/vs/17/release/vc_redist.x64.exe>"},
|
||||||
"infringe": { "reply": "We are aware of the emulator, and are pursuing legal action. They violate our license, and also ship with copyrighted Nintendo files. As such, any references or discussion of the emulator aren't allowed."},
|
"infringe": { "reply": "We are aware of the emulator, and are pursuing legal action. They violate our license, and also ship with copyrighted Nintendo files. As such, any references or discussion of the emulator aren't allowed."},
|
||||||
"android": { "reply": "While we would love to see yuzu ported to Android in the future, we are currently focused on improving the emulator as a whole. Look out for any future announcements, as we'll make sure to let everyone know if an Android build is on the horizon."},
|
"android": { "reply": "While we would love to see yuzu ported to Android in the future, we are currently focused on improving the emulator as a whole. Look out for any future announcements, as we'll make sure to let everyone know if an Android build is on the horizon."},
|
||||||
"firmware": { "reply": "Some games require a firmware dump to work properly. Click the following link for instructions on how to dump the firmware from your Nintendo Switch: <https://yuzu-emu.org/help/quickstart/#dumping-system-update-firmware>"},
|
"firmware": { "reply": "Some games require a firmware dump to work properly. Click the following link for instructions on how to dump the firmware from your Nintendo Switch: <https://yuzu-emu.org/help/quickstart/#dumping-system-firmware>"},
|
||||||
"raptor": { "reply": "Raptor is a 3rd party service that provides a paid alternative to Nintendo Switch Online. We are not associated with Raptor in anyway. After key emulation members and the discerning public shared their opinion with us, we cut all ties with Raptor immediately in 2020. This new fork was made without our permission or cooperation and does not have permission to use the \"yuzu\" name or branding. At this time, we have no plans to add support for any 3rd party services, including Raptor.\n\nAs per our normal policies, we only provide support for our official releases and discussion of any unofficial builds isn't allowed."},
|
"raptor": { "reply": "Raptor is a 3rd party service that provides a paid alternative to Nintendo Switch Online. We are not associated with Raptor in anyway. After key emulation members and the discerning public shared their opinion with us, we cut all ties with Raptor immediately in 2020. This new fork was made without our permission or cooperation and does not have permission to use the \"yuzu\" name or branding. At this time, we have no plans to add support for any 3rd party services, including Raptor.\n\nAs per our normal policies, we only provide support for our official releases and discussion of any unofficial builds isn't allowed."},
|
||||||
"role": { "reply": "To claim your Patreon Discord role, please follow this guide: <https://support.patreon.com/hc/en-us/articles/212052266-Get-my-Discord-role>"},
|
"role": { "reply": "To claim your Patreon Discord role, please follow this guide: <https://support.patreon.com/hc/en-us/articles/212052266-Get-my-Discord-role>"},
|
||||||
"release": { "reply": "yuzu builds can be manually downloaded on Github: <https://github.com/yuzu-emu/yuzu-mainline/releases>"}
|
"release": { "reply": "yuzu builds can be manually downloaded on Github: <https://github.com/yuzu-emu/yuzu-mainline/releases>"},
|
||||||
|
"rec": { "reply": "For information on recommended settings and GPU drivers for yuzu, please refer to this page: <https://community.citra-emu.org/t/recommended-settings/319349>"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"./typings",
|
"./typings",
|
||||||
"./node_modules/@types/"
|
"./node_modules/@types/"
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*"
|
"src/**/*"
|
||||||
|
|
Loading…
Reference in a new issue