mirror of
https://github.com/MetaFam/TheGame.git
synced 2026-02-11 14:34:56 -05:00
Finalize setEthAddress command
This commit is contained in:
committed by
Alec LaLonde
parent
0d6f01d3a2
commit
a512b0ac76
27
packages/@types/sourcecred/index.d.ts
vendored
27
packages/@types/sourcecred/index.d.ts
vendored
@@ -761,46 +761,45 @@ declare module 'sourcecred' {
|
||||
ledger: Ledger;
|
||||
persist: () => Promise<ReloadResult>;
|
||||
}
|
||||
|
||||
|
||||
export interface Ledger {
|
||||
accounts: () => SCAccountInfo[];
|
||||
account: (id: string) => SCAccountInfo;
|
||||
accountByAddress: (address: string) => SCAccountInfo;
|
||||
addAlias: (identityId: any, alias: any) => void;
|
||||
activate: (identityId: any) => void;
|
||||
}
|
||||
|
||||
|
||||
export interface ReloadResult {
|
||||
error: string | null;
|
||||
localChanges: any;
|
||||
}
|
||||
|
||||
|
||||
export interface SCReadInstance {
|
||||
readCredGraph: () => Promise<CredGraph>;
|
||||
}
|
||||
|
||||
export type CredGraph = {
|
||||
|
||||
}
|
||||
|
||||
|
||||
export type CredGraph = Record<string, unknown>;
|
||||
|
||||
export interface SCAccountsData {
|
||||
accounts: SCAccount[];
|
||||
intervalEndpoints: number[];
|
||||
unclaimedAliases: SCUnclaimedAlias[];
|
||||
}
|
||||
|
||||
|
||||
export interface SCAccount {
|
||||
account: SCAccountInfo;
|
||||
cred: number[];
|
||||
totalCred: number;
|
||||
}
|
||||
|
||||
|
||||
export interface SCAccountInfo {
|
||||
active: boolean;
|
||||
balance: string;
|
||||
identity: SCIdentity;
|
||||
paid: string;
|
||||
}
|
||||
|
||||
|
||||
export interface SCIdentity {
|
||||
address: string;
|
||||
aliases: SCAlias[];
|
||||
@@ -808,18 +807,18 @@ declare module 'sourcecred' {
|
||||
name: string;
|
||||
subtype: string;
|
||||
}
|
||||
|
||||
|
||||
export interface SCAlias {
|
||||
address: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
|
||||
export interface SCUnclaimedAlias {
|
||||
alias: SCAlias;
|
||||
cred: number[];
|
||||
totalCred: number;
|
||||
}
|
||||
|
||||
|
||||
export interface AddressBookEntry {
|
||||
name: string;
|
||||
createdAt: number;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"start": "node ./dist/start.js",
|
||||
"build": "yarn generate && tsc -b",
|
||||
"dev": "concurrently \"yarn dev-ts\" \"yarn generate --watch\"",
|
||||
"dev-ts": "ts-node-dev --exit-child --respawn -- src/index.ts",
|
||||
"dev-ts": "ts-node-dev --exit-child --respawn -- src/start.ts",
|
||||
"typecheck": "yarn build",
|
||||
"precommit": "yarn lint-staged",
|
||||
"generate": "graphql-codegen --config=codegen.yml",
|
||||
|
||||
@@ -27,10 +27,7 @@ function parseEnv<T extends string | number>(
|
||||
export const CONFIG: IConfig = {
|
||||
port: parseEnv(process.env.PORT, 5000),
|
||||
graphqlURL: (() => {
|
||||
const {
|
||||
GRAPHQL_URL: url,
|
||||
GRAPHQL_HOST: host,
|
||||
} = process.env;
|
||||
const { GRAPHQL_URL: url, GRAPHQL_HOST: host } = process.env;
|
||||
|
||||
if (url) return url;
|
||||
if (host) {
|
||||
@@ -38,7 +35,10 @@ export const CONFIG: IConfig = {
|
||||
}
|
||||
return 'http://localhost:8080/v1/graphql';
|
||||
})(),
|
||||
adminKey: parseEnv(process.env.HASURA_GRAPHQL_ADMIN_SECRET, 'metagame_secret'),
|
||||
adminKey: parseEnv(
|
||||
process.env.HASURA_GRAPHQL_ADMIN_SECRET,
|
||||
'metagame_secret',
|
||||
),
|
||||
frontendUrl: parseEnv(process.env.FRONTEND_URL, 'http://localhost:3000'),
|
||||
githubApiToken: parseEnv(process.env.GITHUB_API_TOKEN, ''),
|
||||
discordBotToken: parseEnv(process.env.DISCORD_BOT_TOKEN, ''),
|
||||
|
||||
@@ -4,7 +4,8 @@ import * as Path from 'path';
|
||||
@Discord('', {
|
||||
import: [
|
||||
// We are using tsc, so we want to load the compiled files
|
||||
Path.join(__dirname, "commands", "*.js"),
|
||||
Path.join(__dirname, 'commands', '*.ts'),
|
||||
Path.join(__dirname, 'commands', '*.js'),
|
||||
],
|
||||
})
|
||||
export abstract class AppDiscord {
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { Constants } from "@metafam/utils";
|
||||
import { Command, CommandMessage } from "@typeit/discord";
|
||||
import { MessageEmbed, Snowflake } from "discord.js";
|
||||
import fetch from "node-fetch";
|
||||
import { SCAccount, SCAccountsData, SCAlias, sourcecred as sc } from "sourcecred";
|
||||
import { Constants } from '@metafam/utils';
|
||||
import { Command, CommandMessage } from '@typeit/discord';
|
||||
import { MessageEmbed, Snowflake } from 'discord.js';
|
||||
import fetch from 'node-fetch';
|
||||
import {
|
||||
SCAccount,
|
||||
SCAccountsData,
|
||||
SCAlias,
|
||||
sourcecred as sc,
|
||||
} from 'sourcecred';
|
||||
|
||||
import { getDiscordId, replyWithUnexpectedError } from "../../utils";
|
||||
import { getDiscordId, replyWithUnexpectedError } from '../../utils';
|
||||
|
||||
export class GetXpCommand {
|
||||
// todo rename to xp once previous bot is disabled
|
||||
@@ -14,16 +19,20 @@ export class GetXpCommand {
|
||||
try {
|
||||
if (message.args.discordUser) {
|
||||
targetUserDiscordId = getDiscordId(message.args.discordUser);
|
||||
} else if (message.member?.id ) {
|
||||
} else if (message.member?.id) {
|
||||
targetUserDiscordId = message.member.id;
|
||||
}
|
||||
} catch (e) {
|
||||
await message.reply(`Could not recognize user ${message.args.discordUser}. Try \`!ac help\` if you need help.`);
|
||||
await message.reply(
|
||||
`Could not recognize user ${message.args.discordUser}. Try \`!ac help\` if you need help.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetUserDiscordId.trim().length === 0) {
|
||||
await message.reply(`Could not recognize user. Try \`!ac help\` if you need help.`);
|
||||
await message.reply(
|
||||
`Could not recognize user. Try \`!ac help\` if you need help.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -34,60 +43,66 @@ export class GetXpCommand {
|
||||
await fetch(Constants.SC_ACCOUNTS_FILE)
|
||||
).json();
|
||||
|
||||
const scAccount = accountsData.accounts.find(account => filterAccount(account, targetUserDiscordId));
|
||||
const scAccount = accountsData.accounts.find((account) =>
|
||||
filterAccount(account, targetUserDiscordId),
|
||||
);
|
||||
if (scAccount != null) {
|
||||
const userTotalCred = scAccount.totalCred;
|
||||
const numWeeks = scAccount.cred.length;
|
||||
const userWeeklyCred = scAccount.cred;
|
||||
const variation =
|
||||
(100 * (userWeeklyCred[numWeeks - 1] - userWeeklyCred[numWeeks - 2])) /
|
||||
(100 *
|
||||
(userWeeklyCred[numWeeks - 1] - userWeeklyCred[numWeeks - 2])) /
|
||||
userWeeklyCred[numWeeks - 2];
|
||||
|
||||
const description = message.member?.id === targetUserDiscordId ?
|
||||
`${discordUser}, here is your XP progression in MetaGame` :
|
||||
`Here is the XP progression of ${discordUser} in MetaGame`;
|
||||
const description =
|
||||
message.member?.id === targetUserDiscordId
|
||||
? `${discordUser}, here is your XP progression in MetaGame`
|
||||
: `Here is the XP progression of ${discordUser} in MetaGame`;
|
||||
|
||||
await message.reply(new MessageEmbed()
|
||||
.setColor('#ff3864')
|
||||
.setDescription(description)
|
||||
.setTitle(`MetaGame XP`)
|
||||
.setURL("https://xp.metagame.wtf/#/explorer")
|
||||
.setTimestamp()
|
||||
.setThumbnail(
|
||||
'https://raw.githubusercontent.com/sourcecred/sourcecred/master/src/assets/logo/rasterized/logo_64.png',
|
||||
)
|
||||
.addFields(
|
||||
{
|
||||
name: 'Total',
|
||||
value: `${Math.round(userTotalCred)} XP`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Last week ',
|
||||
value: `${userWeeklyCred[numWeeks - 1].toPrecision(3)} XP`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Week before',
|
||||
value: `${userWeeklyCred[numWeeks - 2].toPrecision(4)} XP`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Weekly Change',
|
||||
value: `${variation.toPrecision(2)}%`,
|
||||
inline: true,
|
||||
},
|
||||
)
|
||||
.setFooter(
|
||||
'Bot made by MetaFam',
|
||||
'https://wiki.metagame.wtf/img/mg-crystal.png',
|
||||
),
|
||||
await message.reply(
|
||||
new MessageEmbed()
|
||||
.setColor('#ff3864')
|
||||
.setDescription(description)
|
||||
.setTitle(`MetaGame XP`)
|
||||
.setURL('https://xp.metagame.wtf/#/explorer')
|
||||
.setTimestamp()
|
||||
.setThumbnail(
|
||||
'https://raw.githubusercontent.com/sourcecred/sourcecred/master/src/assets/logo/rasterized/logo_64.png',
|
||||
)
|
||||
.addFields(
|
||||
{
|
||||
name: 'Total',
|
||||
value: `${Math.round(userTotalCred)} XP`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Last week ',
|
||||
value: `${userWeeklyCred[numWeeks - 1].toPrecision(3)} XP`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Week before',
|
||||
value: `${userWeeklyCred[numWeeks - 2].toPrecision(4)} XP`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Weekly Change',
|
||||
value: `${variation.toPrecision(2)}%`,
|
||||
inline: true,
|
||||
},
|
||||
)
|
||||
.setFooter(
|
||||
'Bot made by MetaFam',
|
||||
'https://wiki.metagame.wtf/img/mg-crystal.png',
|
||||
),
|
||||
);
|
||||
} else {
|
||||
await message.reply(`I couldn't find ${discordUser} in the ledger! Have you registered yet?`)
|
||||
await message.reply(
|
||||
`I couldn't find ${discordUser} in the ledger! Have you registered yet?`,
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
await replyWithUnexpectedError(message);
|
||||
}
|
||||
}
|
||||
@@ -98,27 +113,32 @@ const filterAccount = (player: SCAccount, targetUserDiscordID: Snowflake) => {
|
||||
// Ignore if the target isn't a USER
|
||||
if (accountInfo.identity.subtype !== 'USER') return false;
|
||||
|
||||
const discordAliases = accountInfo.identity.aliases.filter(
|
||||
alias => {
|
||||
const parts = sc.core.graph.NodeAddress.toParts(alias.address);
|
||||
return parts.indexOf('discord') > 0
|
||||
}
|
||||
);
|
||||
const discordAliases = accountInfo.identity.aliases.filter((alias) => {
|
||||
const parts = sc.core.graph.NodeAddress.toParts(alias.address);
|
||||
return parts.indexOf('discord') > 0;
|
||||
});
|
||||
|
||||
if (discordAliases.length >= 1) {
|
||||
// Retrieve the Discord ID
|
||||
const discordId = discordAliases.find(discordAccount => scAliasMatchesDiscordId(discordAccount, targetUserDiscordID));
|
||||
if (discordId !== undefined){
|
||||
const discordId = discordAliases.find((discordAccount) =>
|
||||
scAliasMatchesDiscordId(discordAccount, targetUserDiscordID),
|
||||
);
|
||||
if (discordId !== undefined) {
|
||||
return accountInfo;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const scAliasMatchesDiscordId = (discordAccount: SCAlias, targetUserDiscordID: Snowflake) => {
|
||||
const discordId = sc.core.graph.NodeAddress.toParts(discordAccount.address)[4];
|
||||
const scAliasMatchesDiscordId = (
|
||||
discordAccount: SCAlias,
|
||||
targetUserDiscordID: Snowflake,
|
||||
) => {
|
||||
const discordId = sc.core.graph.NodeAddress.toParts(
|
||||
discordAccount.address,
|
||||
)[4];
|
||||
if (discordId === targetUserDiscordID) {
|
||||
return discordId;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { CommandMessage } from "@typeit/discord";
|
||||
import { ReloadResult, sourcecred as sc } from "sourcecred";
|
||||
import { Command, CommandMessage } from '@typeit/discord';
|
||||
import { sourcecred as sc } from 'sourcecred';
|
||||
|
||||
import { loadSourceCredLedger, manager } from "../../sourcecred";
|
||||
import { loadSourceCredLedger, manager } from '../../sourcecred';
|
||||
|
||||
const addressUtils = sc.plugins.ethereum.utils.address;
|
||||
|
||||
export abstract class SetEthAddress {
|
||||
// @Command('setAddress :ethAddress')
|
||||
@Command('!setAddress :ethAddress')
|
||||
async setAddress(message: CommandMessage) {
|
||||
const res = await loadSourceCredLedger();
|
||||
|
||||
@@ -23,7 +23,7 @@ export abstract class SetEthAddress {
|
||||
baseIdentityProposal,
|
||||
);
|
||||
|
||||
let ethAddress;
|
||||
let ethAddress: string;
|
||||
try {
|
||||
ethAddress = addressUtils.parseAddress(message.args.ethAddress);
|
||||
} catch (e) {
|
||||
@@ -45,10 +45,24 @@ export abstract class SetEthAddress {
|
||||
return;
|
||||
}
|
||||
|
||||
const account = manager.ledger.account(baseIdentityId);
|
||||
|
||||
const existing = account.identity.aliases.find((alias) => {
|
||||
const parts = sc.core.graph.NodeAddress.toParts(alias.address);
|
||||
return parts.indexOf('ethereum') > 0;
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
await message.reply(
|
||||
`You already have linked the following ETH Address: \`${existing.description}\`.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
manager.ledger.addAlias(baseIdentityId, ethAlias);
|
||||
manager.ledger.activate(baseIdentityId);
|
||||
const persistRes: ReloadResult = await manager.persist();
|
||||
const persistRes = await manager.persist();
|
||||
|
||||
if (persistRes.error) {
|
||||
await message.reply(
|
||||
|
||||
@@ -7,6 +7,7 @@ async function createDiscordClient(): Promise<Client> {
|
||||
const client = new Client({
|
||||
classes: [
|
||||
// We are using tsc, so we want to load the compiled files
|
||||
`${__dirname}/discord/**/*.ts`, // glob string to load the classes
|
||||
`${__dirname}/discord/**/*.js`, // glob string to load the classes
|
||||
],
|
||||
silent: false,
|
||||
@@ -14,7 +15,6 @@ async function createDiscordClient(): Promise<Client> {
|
||||
});
|
||||
|
||||
await client.login(CONFIG.discordBotToken);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LedgerManager, ReloadResult, sourcecred } from "sourcecred";
|
||||
import { LedgerManager, ReloadResult, sourcecred } from 'sourcecred';
|
||||
|
||||
import { CONFIG } from './config';
|
||||
|
||||
@@ -8,9 +8,11 @@ const storage = new sourcecred.ledger.storage.GithubStorage({
|
||||
branch: 'master',
|
||||
});
|
||||
|
||||
export const manager: LedgerManager = new sourcecred.ledger.manager.LedgerManager({
|
||||
storage,
|
||||
});
|
||||
export const manager: LedgerManager = new sourcecred.ledger.manager.LedgerManager(
|
||||
{
|
||||
storage,
|
||||
},
|
||||
);
|
||||
|
||||
let loading = false;
|
||||
let ledgerLoadedPromise: Promise<ReloadResult>;
|
||||
@@ -19,7 +21,7 @@ export const loadSourceCredLedger = (): Promise<ReloadResult> => {
|
||||
if (ledgerLoadedPromise == null) {
|
||||
if (!loading) {
|
||||
loading = true;
|
||||
console.log('reloading ledger...')
|
||||
console.log('reloading ledger...');
|
||||
ledgerLoadedPromise = manager.reloadLedger();
|
||||
ledgerLoadedPromise.then(() => {
|
||||
loading = false;
|
||||
@@ -28,4 +30,4 @@ export const loadSourceCredLedger = (): Promise<ReloadResult> => {
|
||||
}
|
||||
|
||||
return ledgerLoadedPromise;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import express from 'express';
|
||||
|
||||
import { createDiscordClient } from ".";
|
||||
import { createDiscordClient } from '.';
|
||||
import { CONFIG } from './config';
|
||||
|
||||
createDiscordClient();
|
||||
const discordClientPromise = createDiscordClient();
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -12,5 +12,7 @@ app.get('/healthz', (_, res) => {
|
||||
});
|
||||
|
||||
app.listen(CONFIG.port, () => {
|
||||
console.log(`Discord bot started on port ${CONFIG.port}`);
|
||||
discordClientPromise.then(() => {
|
||||
console.log(`Discord bot started on port ${CONFIG.port}`);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user