non discogs users

This commit is contained in:
ntr committed 2022-08-06 21:49:40 +10:00
1 parent 66dcdaeb70
commit b4114a2440
8 files changed
+93 -49

No files matched your search

+3 -1
View File
@@ -14,14 +14,16 @@ function Bundle(bundle) {
return ( return (
<div class="bundle"> <div class="bundle">
<h2>{bundle.username} - {bundle.seller}</h2> <h2>{bundle.username} - {bundle.seller}</h2>
<h3>{bundle.total} {bundle.currency}</h3> <h3>{bundle.items.length} items - {bundle.total} {bundle.currency}</h3>
<h4>Ships: {bundle.mentionsAustralia && 'AU'} {bundle.mentionsWorldwide && 'WORLD'}</h4> <h4>Ships: {bundle.mentionsAustralia && 'AU'} {bundle.mentionsWorldwide && 'WORLD'}</h4>
{bundle.items.map(i => ( {bundle.items.map(i => (
<div key={i.id}> <div key={i.id}>
<a href={i.uri}> <a href={i.uri}>
<h4>{i.description}</h4> <h4>{i.description}</h4>
</a> </a>
<h5>{i.user}</h5>
<h5>{i.price} {i.currency}</h5> <h5>{i.price} {i.currency}</h5>
<hr />
</div> </div>
))} ))}
</div> </div>
+1
View File
@@ -28,6 +28,7 @@ html, body {
.bundle { .bundle {
flex: 1; flex: 1;
padding-right: 1em;
} }
} }
+1
View File
@@ -4,6 +4,7 @@ type UUID = string;
type DiscogsName = string; type DiscogsName = string;
type DiscogsListing = number; type DiscogsListing = number;
type DiscogsRelease = number;
type DiscogsSeller = number; type DiscogsSeller = number;
type BundleCandidate = { type BundleCandidate = {
+1 -30
View File
@@ -14,38 +14,9 @@ async function start(log) {
const prisma = new PrismaClient(); const prisma = new PrismaClient();
const pg = pgService(log, prisma); const pg = pgService(log, prisma);
const discogs = discogsService(log, pg); const discogs = discogsService(log, pg);
const api = createApi(log, pg); const api = createApi(log, pg, discogs);
const usernames = [
'vanderbabe',
'margh',
'jmcdermid1',
];
async function populateUserListings(user) {
log.info(user);
const wants = await discogs.wantlist(user);
// const latest = await discogs.wantlistLatest(user);
// if (wants.length !== latest.length)
log.info({ username: user.discogs, wantCount: wants.length });
return Promise.mapSeries(wants, async want => {
const listings = await discogs.listings(want);
const populated = listings.filter(l => l);
log.info({ id: want.id, release: want.release, populated: populated.length, total: listings.length });
return populated;
});
}
// await Promise.mapSeries(usernames, async u => {
// const user = await discogs.user(u)
// return populateUserListings(user);
// });
await api.listen(); await api.listen();
// return getBundles();
} }
async function run() { async function run() {
+2 -2
View File
@@ -25,9 +25,9 @@ model Listing {
model User { model User {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
discogs String? @unique
name String @default("unknown") name String @default("unknown")
data Json discogs String? @unique
data Json?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
+55 -3
View File
@@ -2,13 +2,14 @@ import express from 'express';
import http from 'http'; import http from 'http';
import cors from 'cors'; import cors from 'cors';
import { groupBy } from 'lodash'; import { groupBy } from 'lodash';
import Bluebird from 'bluebird';
import type Log from 'bunyan'; import type Log from 'bunyan';
import { Pg } from './pg'; import { Pg } from './pg';
import type { Listing, User, Prisma } from '@prisma/client'; import type { Listing, User, Want, Prisma } from '@prisma/client';
export default function createApi(log: Log, pg: Pg) { export default function createApi(log: Log, pg: Pg, discogs) {
const PORT = 41337; const PORT = 41337;
const app = express(); const app = express();
@@ -32,7 +33,7 @@ export default function createApi(log: Log, pg: Pg) {
currency: l.data.original_price.curr_abbr, currency: l.data.original_price.curr_abbr,
condition: l.data.condition, condition: l.data.condition,
uri: l.data.uri, uri: l.data.uri,
user: l.want.user.discogs, user: l.want.user.name,
})); }));
const shipping = b[0]?.data.seller.shipping; const shipping = b[0]?.data.seller.shipping;
@@ -57,6 +58,24 @@ export default function createApi(log: Log, pg: Pg) {
} }
async function populateUserListings(user: User) {
log.info(user);
const wants = await discogs.wantlist(user);
// const latest = await discogs.wantlistLatest(user);
// if (wants.length !== latest.length)
log.info({ username: user.discogs, wantCount: wants.length });
return Bluebird.mapSeries<Want, Listing[]>(wants, async want => {
const listings = await discogs.listings(want);
const populated = listings.filter(l => l);
log.info({ id: want.id, release: want.release, populated: populated.length, total: listings.length });
return populated;
});
}
function listen() { function listen() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
server.on('error', err => { server.on('error', err => {
@@ -70,6 +89,7 @@ export default function createApi(log: Log, pg: Pg) {
} }
app.use(cors()); app.use(cors());
app.use(express.json())
app.get('/bundles', async (req, res, next) => { app.get('/bundles', async (req, res, next) => {
const bundles = await getBundles(); const bundles = await getBundles();
@@ -77,6 +97,38 @@ export default function createApi(log: Log, pg: Pg) {
res.json(bundles); res.json(bundles);
}) })
app.get('/user/:id/offers', async function userOffersGet(req, res, next) {
const { id } = req.params;
const user = await pg.userFindId(id);
res.json(user);
});
app.post('/user', async function usersPost(req, res, next) {
const { name } = req.body;
const user = await pg.userUpsert(null, name, null);
res.json(user);
});
app.post('/user/populate', async function usersPopulate(req, res, next) {
const { userId } = req.body;
const user = await pg.userFindId(userId);
const listings = await populateUserListings(user);
res.json(listings);
});
app.post('/want', async function wantPost(req, res, next) {
const { userId, releaseId } = req.body;
const user = await pg.userFindId(userId);
const release = await discogs.release(releaseId);
const want = await pg.wantUpsert(release, user);
return res.json(want);
});
app.use(function errorHandler(req, res, next, error) {
log.warn(error);
res.status(500).send({ error });
});
return { return {
app, app,
listen, listen,
+14 -2
View File
@@ -35,13 +35,19 @@ export default function discogs(log: Log, pg: Pg) {
const user = await pg.userFindName(discogs); const user = await pg.userFindName(discogs);
if (user) return user; if (user) return user;
log.debug('fetching user', discogs); log.debug('fetching user', discogs);
const res = await api.get(`${apiBase}/users/${discogs}`); const { data } = await api.get(`${apiBase}/users/${discogs}`);
return pg.userUpsert(res.data); return pg.userUpsert(data.username, data.username, data);
} }
async function wantlist(user: User): Promise<Want[]> { async function wantlist(user: User): Promise<Want[]> {
const stored = await pg.userWants(user); const stored = await pg.userWants(user);
if (stored.length) return stored; if (stored.length) return stored;
if (!user.discogs) {
log.error(user, 'attempted to fetch wantlist of non discogs user');
throw new Error('User is not associated with a discogs account');
}
return wantlistLatest(user); return wantlistLatest(user);
} }
@@ -51,6 +57,11 @@ export default function discogs(log: Log, pg: Pg) {
return Bluebird.mapSeries(wants, async r => pg.wantUpsert(r, user)); return Bluebird.mapSeries(wants, async r => pg.wantUpsert(r, user));
} }
async function release(id: DiscogsRelease): Promise<any> {
const { data } = await api.get(`${apiBase}/releases/${id}`);
return data;
}
async function inventory(user: string) { async function inventory(user: string) {
const res = await api.get(`${apiBase}/users/${user}/inventory`); const res = await api.get(`${apiBase}/users/${user}/inventory`);
return res.data.listings; return res.data.listings;
@@ -91,5 +102,6 @@ export default function discogs(log: Log, pg: Pg) {
inventory, inventory,
listings, listings,
listing, listing,
release,
}; };
} }
+16 -11
View File
@@ -5,7 +5,7 @@ import * as Bluebird from 'bluebird';
export interface Pg { export interface Pg {
userFindId: (id: UUID) => Promise<User>, userFindId: (id: UUID) => Promise<User>,
userFindName: (name: DiscogsName) => Promise<User>, userFindName: (name: DiscogsName) => Promise<User>,
userUpsert: (user: User) => Promise<User>, userUpsert: (discogs: DiscogsName | null, name: string, data: any) => Promise<User>,
userWants: (user: User) => Promise<Want[]>, userWants: (user: User) => Promise<Want[]>,
wantUpsert: (want: Want, user: User) => Promise<Want>, wantUpsert: (want: Want, user: User) => Promise<Want>,
@@ -17,7 +17,7 @@ export interface Pg {
} }
export default function createPg(log: Log, prisma: PrismaClient): Pg { export default function createPg(log: Log, prisma: PrismaClient): Pg {
async function userFindId(id) { async function userFindId(id: UUID) {
return prisma.user.findUnique({ where: { id }}); return prisma.user.findUnique({ where: { id }});
} }
@@ -29,18 +29,23 @@ export default function createPg(log: Log, prisma: PrismaClient): Pg {
return prisma.want.findMany({ where: { userId: user.id }}); return prisma.want.findMany({ where: { userId: user.id }});
} }
async function userUpsert(user) { async function userUpsert(discogs: DiscogsName | null, name: string, data: any) {
const data = { const insert = {
discogs: user.username, discogs,
data: user as Prisma.JsonObject, name,
data,
}; };
return prisma.user.upsert({ if (discogs) return prisma.user.upsert({
where: { where: {
discogs: user.username, discogs,
}, },
update: data, update: insert,
create: data, create: insert,
});
return prisma.user.create({
data: { name },
}); });
} }
@@ -111,7 +116,7 @@ export default function createPg(log: Log, prisma: PrismaClient): Pg {
select select
seller, count(distinct("wantId")), array_agg(id) as listings seller, count(distinct("wantId")), array_agg(id) as listings
from from
"Listing" listings
group by group by
seller seller
order by order by