Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 130c084c20 | |||
| 2cf75c3851 | |||
| d27d54804a |
7
app.go
7
app.go
@@ -36,7 +36,7 @@ func (a *App) startup(ctx context.Context) {
|
||||
}
|
||||
|
||||
// Add location read scope so we can fetch character locations
|
||||
a.ssi = NewESISSO(clientID, redirectURI, []string{
|
||||
ssi, err := NewESISSO(clientID, redirectURI, []string{
|
||||
"esi-location.read_location.v1",
|
||||
"esi-location.read_ship_type.v1",
|
||||
"esi-mail.organize_mail.v1",
|
||||
@@ -76,6 +76,11 @@ func (a *App) startup(ctx context.Context) {
|
||||
"esi-characters.read_titles.v1",
|
||||
"esi-characters.read_fw_stats.v1",
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: Failed to initialize ESI SSO: %v\n", err)
|
||||
return
|
||||
}
|
||||
a.ssi = ssi
|
||||
}
|
||||
|
||||
// Greet returns a greeting for the given name
|
||||
|
||||
32
esi_sso.go
32
esi_sso.go
@@ -74,6 +74,10 @@ type ESIToken struct {
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (ESIToken) TableName() string {
|
||||
return "esi_tokens"
|
||||
}
|
||||
|
||||
type CharacterInfo struct {
|
||||
CharacterID int64 `json:"character_id"`
|
||||
CharacterName string `json:"character_name"`
|
||||
@@ -108,28 +112,42 @@ type SystemKills struct {
|
||||
NpcKills int64 `json:"npc_kills"`
|
||||
}
|
||||
|
||||
func NewESISSO(clientID string, redirectURI string, scopes []string) *ESISSO {
|
||||
func NewESISSO(clientID string, redirectURI string, scopes []string) (*ESISSO, error) {
|
||||
s := &ESISSO{
|
||||
clientID: clientID,
|
||||
redirectURI: redirectURI,
|
||||
scopes: scopes,
|
||||
}
|
||||
_ = s.initDB()
|
||||
return s
|
||||
if err := s.initDB(); err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize database: %w", err)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *ESISSO) initDB() error {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to get user home directory: %w", err)
|
||||
}
|
||||
dbPath := filepath.Join(home, ".industrializer", "sqlite-latest.sqlite")
|
||||
db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to open database at %s: %w", dbPath, err)
|
||||
}
|
||||
if err := db.AutoMigrate(&ESIToken{}); err != nil {
|
||||
return err
|
||||
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get underlying sql.DB: %w", err)
|
||||
}
|
||||
|
||||
if err := sqlDB.Ping(); err != nil {
|
||||
return fmt.Errorf("failed to ping database: %w", err)
|
||||
}
|
||||
|
||||
if !db.Migrator().HasTable(&ESIToken{}) {
|
||||
if err := db.Migrator().CreateTable(&ESIToken{}); err != nil {
|
||||
return fmt.Errorf("failed to create table esi_tokens: %w", err)
|
||||
}
|
||||
}
|
||||
s.db = db
|
||||
return nil
|
||||
|
||||
@@ -14,6 +14,7 @@ interface MapNodeProps {
|
||||
type: 'region' | 'system';
|
||||
security?: number;
|
||||
signatures?: number;
|
||||
jove_observatory?: boolean;
|
||||
isDraggable?: boolean;
|
||||
disableNavigate?: boolean;
|
||||
jumps?: number;
|
||||
@@ -37,6 +38,7 @@ export const MapNode: React.FC<MapNodeProps> = ({
|
||||
type,
|
||||
security,
|
||||
signatures,
|
||||
jove_observatory,
|
||||
isDraggable = false,
|
||||
disableNavigate = false,
|
||||
jumps,
|
||||
@@ -238,6 +240,29 @@ export const MapNode: React.FC<MapNodeProps> = ({
|
||||
currentY += 15;
|
||||
}
|
||||
|
||||
// Add jove observatory icon if present
|
||||
if (jove_observatory) {
|
||||
textElements.push(
|
||||
<text
|
||||
key="jove_observatory"
|
||||
x="0"
|
||||
y={currentY}
|
||||
textAnchor="middle"
|
||||
fill="#fbbf24"
|
||||
fontSize="12"
|
||||
className="pointer-events-none select-none"
|
||||
style={{
|
||||
textShadow: '1px 1px 2px rgba(0,0,0,0.8)',
|
||||
vectorEffect: 'non-scaling-stroke'
|
||||
}}
|
||||
transform={`scale(${(1 / (1200 / viewBoxWidth)) * labelScale})`}
|
||||
>
|
||||
🔭
|
||||
</text>
|
||||
);
|
||||
currentY += 15;
|
||||
}
|
||||
|
||||
// Add jumps if enabled and present
|
||||
if (showJumps && jumps !== undefined) {
|
||||
textElements.push(
|
||||
|
||||
@@ -1107,6 +1107,7 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
||||
type="system"
|
||||
security={system.security}
|
||||
signatures={system.signatures}
|
||||
jove_observatory={system.jove_observatory}
|
||||
isDraggable={isWormholeRegion}
|
||||
disableNavigate={viaMode}
|
||||
jumps={getSystemJumps(system.solarSystemName)}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { System } from '@/lib/types';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import pb from '@/lib/pocketbase';
|
||||
import { SystemResponse } from '@/lib/pbtypes';
|
||||
|
||||
const pocketbaseUrl = `https://evebase.site.quack-lab.dev/api/collections/regionview/records`;
|
||||
|
||||
@@ -23,6 +25,26 @@ const fetchRegionData = async (regionName: string): Promise<Map<string, System>>
|
||||
system.signatures = systemSigs.sigcount;
|
||||
}
|
||||
}
|
||||
|
||||
const systemNames = Array.from(systemsMap.keys());
|
||||
if (systemNames.length > 0) {
|
||||
const filter = systemNames.map(name => `name='${name}'`).join(' || ');
|
||||
try {
|
||||
const systemRecords = await pb.collection('system').getFullList<SystemResponse>({
|
||||
filter: `(${filter})`,
|
||||
batch: 1000
|
||||
});
|
||||
for (const record of systemRecords) {
|
||||
const system = systemsMap.get(record.name);
|
||||
if (system && record.jove_observatory) {
|
||||
system.jove_observatory = record.jove_observatory;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to fetch jove_observatory data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
return systemsMap;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@ export enum Collections {
|
||||
|
||||
// Alias types for improved usability
|
||||
export type IsoDateString = string
|
||||
export type IsoAutoDateString = string & { readonly autodate: unique symbol }
|
||||
export type RecordIdString = string
|
||||
export type FileNameString = string & { readonly filename: unique symbol }
|
||||
export type HTMLString = string
|
||||
|
||||
type ExpandType<T> = unknown extends T
|
||||
@@ -52,66 +54,66 @@ export type AuthSystemFields<T = unknown> = {
|
||||
|
||||
export type AuthoriginsRecord = {
|
||||
collectionRef: string
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
fingerprint: string
|
||||
id: string
|
||||
recordRef: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type ExternalauthsRecord = {
|
||||
collectionRef: string
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
id: string
|
||||
provider: string
|
||||
providerId: string
|
||||
recordRef: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type MfasRecord = {
|
||||
collectionRef: string
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
id: string
|
||||
method: string
|
||||
recordRef: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type OtpsRecord = {
|
||||
collectionRef: string
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
id: string
|
||||
password: string
|
||||
recordRef: string
|
||||
sentTo?: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type SuperusersRecord = {
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
email: string
|
||||
emailVisibility?: boolean
|
||||
id: string
|
||||
password: string
|
||||
tokenKey: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
verified?: boolean
|
||||
}
|
||||
|
||||
export type IndBillitemRecord = {
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
id: string
|
||||
name: string
|
||||
quantity: number
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type IndCharRecord = {
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
id: string
|
||||
name: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export enum IndJobStatusOptions {
|
||||
@@ -132,7 +134,7 @@ export type IndJobRecord = {
|
||||
billOfMaterials?: RecordIdString[]
|
||||
character?: RecordIdString
|
||||
consumedMaterials?: RecordIdString[]
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
expenditures?: RecordIdString[]
|
||||
id: string
|
||||
income?: RecordIdString[]
|
||||
@@ -148,13 +150,13 @@ export type IndJobRecord = {
|
||||
saleEnd?: IsoDateString
|
||||
saleStart?: IsoDateString
|
||||
status: IndJobStatusOptions
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type IndTransactionRecord = {
|
||||
buyer?: string
|
||||
corporation?: string
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
date: IsoDateString
|
||||
id: string
|
||||
itemName: string
|
||||
@@ -163,7 +165,7 @@ export type IndTransactionRecord = {
|
||||
quantity: number
|
||||
totalPrice: number
|
||||
unitPrice: number
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
wallet?: string
|
||||
}
|
||||
|
||||
@@ -175,7 +177,7 @@ export type RegionviewRecord = {
|
||||
}
|
||||
|
||||
export type SignatureRecord = {
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
dangerous?: boolean
|
||||
id: string
|
||||
identifier: string
|
||||
@@ -184,20 +186,20 @@ export type SignatureRecord = {
|
||||
scanned?: string
|
||||
system: RecordIdString
|
||||
type?: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type SignatureNoteRulesRecord = {
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
enabled?: boolean
|
||||
id: string
|
||||
note: string
|
||||
regex: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type SigviewRecord = {
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
dangerous?: boolean
|
||||
id: string
|
||||
identifier: string
|
||||
@@ -207,24 +209,25 @@ export type SigviewRecord = {
|
||||
sysid?: RecordIdString
|
||||
system: string
|
||||
type?: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type SystemRecord = {
|
||||
connectedTo?: string
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
id: string
|
||||
jove_observatory?: boolean
|
||||
name: string
|
||||
region: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
}
|
||||
|
||||
export type WormholeSystemsRecord = {
|
||||
connectedSystems?: string
|
||||
created?: IsoDateString
|
||||
created: IsoAutoDateString
|
||||
id: string
|
||||
solarSystemName: string
|
||||
updated?: IsoDateString
|
||||
updated: IsoAutoDateString
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
@@ -284,23 +287,68 @@ export type CollectionResponses = {
|
||||
wormholeSystems: WormholeSystemsResponse
|
||||
}
|
||||
|
||||
// Utility types for create/update operations
|
||||
|
||||
type ProcessCreateAndUpdateFields<T> = Omit<{
|
||||
// Omit AutoDate fields
|
||||
[K in keyof T as Extract<T[K], IsoAutoDateString> extends never ? K : never]:
|
||||
// Convert FileNameString to File
|
||||
T[K] extends infer U ?
|
||||
U extends (FileNameString | FileNameString[]) ?
|
||||
U extends any[] ? File[] : File
|
||||
: U
|
||||
: never
|
||||
}, 'id'>
|
||||
|
||||
// Create type for Auth collections
|
||||
export type CreateAuth<T> = {
|
||||
id?: RecordIdString
|
||||
email: string
|
||||
emailVisibility?: boolean
|
||||
password: string
|
||||
passwordConfirm: string
|
||||
verified?: boolean
|
||||
} & ProcessCreateAndUpdateFields<T>
|
||||
|
||||
// Create type for Base collections
|
||||
export type CreateBase<T> = {
|
||||
id?: RecordIdString
|
||||
} & ProcessCreateAndUpdateFields<T>
|
||||
|
||||
// Update type for Auth collections
|
||||
export type UpdateAuth<T> = Partial<
|
||||
Omit<ProcessCreateAndUpdateFields<T>, keyof AuthSystemFields>
|
||||
> & {
|
||||
email?: string
|
||||
emailVisibility?: boolean
|
||||
oldPassword?: string
|
||||
password?: string
|
||||
passwordConfirm?: string
|
||||
verified?: boolean
|
||||
}
|
||||
|
||||
// Update type for Base collections
|
||||
export type UpdateBase<T> = Partial<
|
||||
Omit<ProcessCreateAndUpdateFields<T>, keyof BaseSystemFields>
|
||||
>
|
||||
|
||||
// Get the correct create type for any collection
|
||||
export type Create<T extends keyof CollectionResponses> =
|
||||
CollectionResponses[T] extends AuthSystemFields
|
||||
? CreateAuth<CollectionRecords[T]>
|
||||
: CreateBase<CollectionRecords[T]>
|
||||
|
||||
// Get the correct update type for any collection
|
||||
export type Update<T extends keyof CollectionResponses> =
|
||||
CollectionResponses[T] extends AuthSystemFields
|
||||
? UpdateAuth<CollectionRecords[T]>
|
||||
: UpdateBase<CollectionRecords[T]>
|
||||
|
||||
// Type for usage with type asserted PocketBase instance
|
||||
// https://github.com/pocketbase/js-sdk#specify-typescript-definitions
|
||||
|
||||
export type TypedPocketBase = PocketBase & {
|
||||
collection(idOrName: '_authOrigins'): RecordService<AuthoriginsResponse>
|
||||
collection(idOrName: '_externalAuths'): RecordService<ExternalauthsResponse>
|
||||
collection(idOrName: '_mfas'): RecordService<MfasResponse>
|
||||
collection(idOrName: '_otps'): RecordService<OtpsResponse>
|
||||
collection(idOrName: '_superusers'): RecordService<SuperusersResponse>
|
||||
collection(idOrName: 'ind_billItem'): RecordService<IndBillitemResponse>
|
||||
collection(idOrName: 'ind_char'): RecordService<IndCharResponse>
|
||||
collection(idOrName: 'ind_job'): RecordService<IndJobResponse>
|
||||
collection(idOrName: 'ind_transaction'): RecordService<IndTransactionResponse>
|
||||
collection(idOrName: 'regionview'): RecordService<RegionviewResponse>
|
||||
collection(idOrName: 'signature'): RecordService<SignatureResponse>
|
||||
collection(idOrName: 'signature_note_rules'): RecordService<SignatureNoteRulesResponse>
|
||||
collection(idOrName: 'sigview'): RecordService<SigviewResponse>
|
||||
collection(idOrName: 'system'): RecordService<SystemResponse>
|
||||
collection(idOrName: 'wormholeSystems'): RecordService<WormholeSystemsResponse>
|
||||
}
|
||||
export type TypedPocketBase = {
|
||||
collection<T extends keyof CollectionResponses>(
|
||||
idOrName: T
|
||||
): RecordService<CollectionResponses[T]>
|
||||
} & PocketBase
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface System {
|
||||
y: number;
|
||||
security?: number;
|
||||
signatures?: number;
|
||||
jove_observatory?: boolean;
|
||||
connectedSystems: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user