..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 | import axios from 'axios';
import { Repository } from 'typeorm';
import { FribbMapping } from '../entities/FribbMapping';
import AppDataSource from '../database/data-source';
import Logger from '../utils/logger';
export interface FribbList {
livechart_id: number;
thetvdb_id: number;
"anime-planet_id": string;
imdb_id: string;
anisearch_id: number;
themoviedb_id: number;
anidb_id: number;
kitsu_id: number;
mal_id: number;
type: string;
"notify.moe_id": string;
anilist_id: number;
}
export class FribbSyncTask {
private repository: Repository<FribbMapping>;
private readonly FRIBB_URL = "https://raw.githubusercontent.com/Fribb/anime-lists/master/anime-list-full.json";
constructor() {
this.repository = AppDataSource.getRepository(FribbMapping);
}
async execute(): Promise<void> {
try {
Logger.info('Starting Fribb sync', { timestamp: true, prefix: 'FribbSync' });
// Fetch the data
const response = await axios.get<FribbList[]>(this.FRIBB_URL);
const mappings = response.data;
// Process in batches
const batchSize = 100;
for (let i = 0; i < mappings.length; i += batchSize) {
const batch = mappings.slice(i, i + batchSize);
await this.processBatch(batch);
Logger.info(`Processed ${i + batch.length}/${mappings.length} mappings`, {
timestamp: true,
prefix: 'FribbSync'
});
}
Logger.success('Fribb sync completed', { timestamp: true, prefix: 'FribbSync' });
} catch (error) {
Logger.error(`Fribb sync failed: ${error}`, { timestamp: true, prefix: 'FribbSync' });
throw error;
}
}
private async processBatch(mappings: FribbList[]): Promise<void> {
for (const mapping of mappings) {
try {
// Create composite key for MAL and AniList IDs if both exist
const mal_anilist_composite = mapping.mal_id && mapping.anilist_id
? `${mapping.mal_id}-${mapping.anilist_id}`
: null;
// Try to find existing mapping by livechart_id or mal_anilist_composite
let entity = await this.repository.findOne({
where: [
{ livechart_id: mapping.livechart_id },
...(mal_anilist_composite
? [{ mal_anilist_composite: mal_anilist_composite }]
: [])
]
});
if (entity) {
// Update existing entity
Object.assign(entity, mapping, { mal_anilist_composite });
await this.repository.save(entity);
} else {
// Create new entity
entity = this.repository.create({
...mapping,
mal_anilist_composite: mal_anilist_composite || undefined
});
await this.repository.save(entity);
}
} catch (error) {
Logger.error(`Error processing mapping: ${JSON.stringify(mapping)}: ${error}`, {
timestamp: true,
prefix: 'FribbSync'
});
}
}
}
}
// Initialize and export the task configuration
export const fribbSyncTask = {
name: 'FribbSync',
interval: 7 * 24 * 60 * 60 * 1000, // 1 week in milliseconds
execute: async () => {
const task = new FribbSyncTask();
await task.execute();
}
};
|
|