Skip to content

Commit

Permalink
🐛 FIX: handle subscriptions importing errors (ViewTube#1478)
Browse files Browse the repository at this point in the history
  • Loading branch information
cyacedev committed Jul 29, 2022
1 parent a206265 commit b7ac579
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 51 deletions.
6 changes: 3 additions & 3 deletions client/components/popup/SubscriptionImport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ import { computed, defineComponent, ref } from '@nuxtjs/composition-api';
import CheckBox from '@/components/form/CheckBox.vue';
import BadgeButton from '@/components/buttons/BadgeButton.vue';
import FileButton from '@/components/form/FileButton.vue';
import SubscriptionConverter from '@/plugins/services/subscriptionConverter';
import { convertFromCSVToJson, convertFromOPMLToJson } from '@/plugins/services/subscriptionConverter';
import Spinner from '@/components/Spinner.vue';
import '@/assets/styles/popup.scss';
import { useAxios } from '@/plugins/axiosPlugin';
Expand Down Expand Up @@ -233,7 +233,7 @@ export default defineComponent({
const fileReader = new FileReader();
fileReader.onload = () => {
if (e.target.files[0].name.includes('.csv')) {
subscriptionsToImport.value = SubscriptionConverter.convertFromCSVToJson(
subscriptionsToImport.value = convertFromCSVToJson(
fileReader.result as string
);
}
Expand Down Expand Up @@ -263,7 +263,7 @@ export default defineComponent({
const onOPMLFileChange = (e: any) => {
const fileReader = new FileReader();
fileReader.onload = () => {
subscriptionsToImport.value = SubscriptionConverter.convertFromOPMLToJson(
subscriptionsToImport.value = convertFromOPMLToJson(
fileReader.result as string
);
if (subscriptionsToImport.value === undefined) {
Expand Down
85 changes: 44 additions & 41 deletions client/plugins/services/subscriptionConverter.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,52 @@
import X2js from 'x2js';
import PapaParse from 'papaparse';

export default {
convertFromOPMLToJson(opmlString: string) {
const x2js = new X2js();
const jsonString: any = x2js.xml2js(opmlString);
type Subscription = {
author: string;
authorId: string;
selected: boolean;
};

if (jsonString.opml !== undefined) {
const channelArray = jsonString.opml.body.outline.outline;
const mappedChannelArray = this.mapOMPL(channelArray);
return mappedChannelArray;
}
},
export const convertFromOPMLToJson = (opml: string): Subscription[] => {
const x2js = new X2js();
const jsonString: any = x2js.xml2js(opml);

convertFromCSVToJson(csvString: string) {
const result = PapaParse.parse(csvString, { header: false, skipEmptyLines: true });
result.data.splice(0, 1);
if (result.data[0] !== undefined) {
return this.mapYTTakeout(result.data);
}
},

mapOMPL(array: any[]) {
return array.map((element: { _xmlUrl: string; _title: any; _text: any }) => {
let channelId = new URL(element._xmlUrl).searchParams.get('channel_id');
if (!channelId) {
channelId = element._xmlUrl.match(/(.*\/channel\/)(.*[^\\/])\/?/i)[2];
}
const channelTitle =
element._title === element._text ? element._title : `${element._title} | ${element._text}`;
return {
author: channelTitle,
authorId: channelId,
selected: false
};
});
},
if (jsonString.opml !== undefined) {
const channelArray: Object[] = jsonString.opml.body.outline.outline;
const mappedChannelArray = mapOPML(channelArray);
console.log(JSON.stringify(mappedChannelArray));
return mappedChannelArray;
}
};

mapYTTakeout(array: any[]) {
return array.map((element: Object) => {
return {
author: element[2],
authorId: element[0],
selected: false
};
});
export const convertFromCSVToJson = (csv: string): Subscription[] => {
const result = PapaParse.parse(csv, { header: false, skipEmptyLines: true });
result.data.splice(0, 1);
if (result.data[0] !== undefined) {
return mapYTTakeout(result.data);
}
};

export const mapYTTakeout = (data: any[]): Subscription[] => {
return data.map((element: Object) => {
return {
author: element[2],
authorId: element[0],
selected: false
};
});
};

export const mapOPML = (opml: Object[]): Subscription[] =>
opml.map((row: { _xmlUrl: string; _title: any; _text: any }) => {
const author = row._title === row._text ? row._title : `${row._title} | ${row._text}`;
let authorId = new URL(row._xmlUrl).searchParams.get('channel_id');
if (!authorId) {
authorId = row._xmlUrl.match(/(.*\/channel\/)(.*[^\\/])\/?/i)[2];
}
return {
author,
authorId,
selected: false
};
});
6 changes: 3 additions & 3 deletions server/src/user/subscriptions/subscriptions-job.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ export const getChannelFeed = (
if (data) {
const x2js = new X2js();
const jsonData = x2js.xml2js(data) as any;
if (jsonData.feed.entry) {
if (jsonData.feed) {
let videos: Array<VideoBasicInfoDto> = [];
// For channels that have no videos
if (jsonData.feed.entry.length) {
// For channels that have videos
if (jsonData.feed.entry) {
videos = jsonData.feed.entry.map((video: any) => convertRssVideo(video));
}

Expand Down
8 changes: 4 additions & 4 deletions server/src/user/subscriptions/subscriptions.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,19 +359,19 @@ export class SubscriptionsService {
});
}

await this.subscriptionModel
const channelFeed = await getChannelFeed(channelId);
if (channelFeed) {
await this.subscriptionModel
.findOneAndUpdate({ username }, { username, subscriptions }, { upsert: true })
.exec()
.then()
.catch(_ => {
throw new InternalServerErrorException('Error subscribing to channel');
});

const channelFeed = await getChannelFeed(channelId);
if (channelFeed) {
try {
await this.saveChannelBasicInfo(channelFeed.channel);
await Promise.all(
await Promise.allSettled(
channelFeed.videos.map(vid => {
return this.saveVideoBasicInfo(vid);
})
Expand Down

0 comments on commit b7ac579

Please sign in to comment.