Merge pull request #6882 from talanc/dev
Add support for CSV+ZIP subscriptions (Google Takeout)
This commit is contained in:
commit
f8f2dfce4b
|
@ -184,7 +184,7 @@ dependencies {
|
||||||
// name and the commit hash with the commit hash of the (pushed) commit you want to test
|
// name and the commit hash with the commit hash of the (pushed) commit you want to test
|
||||||
// This works thanks to JitPack: https://jitpack.io/
|
// This works thanks to JitPack: https://jitpack.io/
|
||||||
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
||||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.9'
|
implementation 'com.github.TeamNewPipe:NewPipeExtractor:68f1fa994af78d2cd0f354f9226d5dbe3dc03d54'
|
||||||
|
|
||||||
/** Checkstyle **/
|
/** Checkstyle **/
|
||||||
checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"
|
checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
package org.schabi.newpipe.local.subscription.services;
|
package org.schabi.newpipe.local.subscription.services;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.MainActivity.DEBUG;
|
||||||
|
import static org.schabi.newpipe.streams.io.StoredFileHelper.DEFAULT_MIME;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -46,6 +49,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
|
@ -54,9 +58,6 @@ import io.reactivex.rxjava3.functions.Consumer;
|
||||||
import io.reactivex.rxjava3.functions.Function;
|
import io.reactivex.rxjava3.functions.Function;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
import static org.schabi.newpipe.MainActivity.DEBUG;
|
|
||||||
import static org.schabi.newpipe.streams.io.StoredFileHelper.DEFAULT_MIME;
|
|
||||||
|
|
||||||
public class SubscriptionsImportService extends BaseImportExportService {
|
public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
public static final int CHANNEL_URL_MODE = 0;
|
public static final int CHANNEL_URL_MODE = 0;
|
||||||
public static final int INPUT_STREAM_MODE = 1;
|
public static final int INPUT_STREAM_MODE = 1;
|
||||||
|
@ -89,6 +90,8 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
private String channelUrl;
|
private String channelUrl;
|
||||||
@Nullable
|
@Nullable
|
||||||
private InputStream inputStream;
|
private InputStream inputStream;
|
||||||
|
@Nullable
|
||||||
|
private String inputStreamType;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(final Intent intent, final int flags, final int startId) {
|
public int onStartCommand(final Intent intent, final int flags, final int startId) {
|
||||||
|
@ -111,8 +114,20 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inputStream = new SharpInputStream(
|
final StoredFileHelper fileHelper = new StoredFileHelper(this, uri, DEFAULT_MIME);
|
||||||
new StoredFileHelper(this, uri, DEFAULT_MIME).getStream());
|
inputStream = new SharpInputStream(fileHelper.getStream());
|
||||||
|
inputStreamType = fileHelper.getType();
|
||||||
|
|
||||||
|
if (inputStreamType == null || inputStreamType.equals(DEFAULT_MIME)) {
|
||||||
|
// mime type could not be determined, just take file extension
|
||||||
|
final String name = fileHelper.getName();
|
||||||
|
final int pointIndex = name.lastIndexOf('.');
|
||||||
|
if (pointIndex == -1 || pointIndex >= name.length() - 1) {
|
||||||
|
inputStreamType = DEFAULT_MIME; // no extension, will fail in the extractor
|
||||||
|
} else {
|
||||||
|
inputStreamType = name.substring(pointIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
handleError(e);
|
handleError(e);
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
|
@ -248,9 +263,9 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
final Throwable error = notification.getError();
|
final Throwable error = notification.getError();
|
||||||
final Throwable cause = error.getCause();
|
final Throwable cause = error.getCause();
|
||||||
if (error instanceof IOException) {
|
if (error instanceof IOException) {
|
||||||
throw (IOException) error;
|
throw error;
|
||||||
} else if (cause instanceof IOException) {
|
} else if (cause instanceof IOException) {
|
||||||
throw (IOException) cause;
|
throw cause;
|
||||||
} else if (ExceptionUtils.isNetworkRelated(error)) {
|
} else if (ExceptionUtils.isNetworkRelated(error)) {
|
||||||
throw new IOException(error);
|
throw new IOException(error);
|
||||||
}
|
}
|
||||||
|
@ -280,9 +295,12 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Flowable<List<SubscriptionItem>> importFromInputStream() {
|
private Flowable<List<SubscriptionItem>> importFromInputStream() {
|
||||||
|
Objects.requireNonNull(inputStream);
|
||||||
|
Objects.requireNonNull(inputStreamType);
|
||||||
|
|
||||||
return Flowable.fromCallable(() -> NewPipe.getService(currentServiceId)
|
return Flowable.fromCallable(() -> NewPipe.getService(currentServiceId)
|
||||||
.getSubscriptionExtractor()
|
.getSubscriptionExtractor()
|
||||||
.fromInputStream(inputStream));
|
.fromInputStream(inputStream, inputStreamType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Flowable<List<SubscriptionItem>> importFromPreviousExport() {
|
private Flowable<List<SubscriptionItem>> importFromPreviousExport() {
|
||||||
|
|
|
@ -542,7 +542,7 @@
|
||||||
<string name="previous_export">Previous export</string>
|
<string name="previous_export">Previous export</string>
|
||||||
<string name="subscriptions_import_unsuccessful">Could not import subscriptions</string>
|
<string name="subscriptions_import_unsuccessful">Could not import subscriptions</string>
|
||||||
<string name="subscriptions_export_unsuccessful">Could not export subscriptions</string>
|
<string name="subscriptions_export_unsuccessful">Could not export subscriptions</string>
|
||||||
<string name="import_youtube_instructions">Import YouTube subscriptions from Google takeout:\n\n1. Go to this URL: %1$s\n2. Log in when asked\n3. Click on \"All data included\", then on \"Deselect all\", then select only \"subscriptions\" and click \"OK\"\n4. Click on \"Next step\" and then on \"Create export\"\n5. Click on the \"Download\" button after it appears and \n6. From the downloaded takeout zip extract the .json file (usually under \"YouTube and YouTube Music/subscriptions/subscriptions.json\") and import it here.</string>
|
<string name="import_youtube_instructions">Import YouTube subscriptions from Google takeout:\n\n1. Go to this URL: %1$s\n2. Log in when asked\n3. Click on \"All data included\", then on \"Deselect all\", then select only \"subscriptions\" and click \"OK\"\n4. Click on \"Next step\" and then on \"Create export\"\n5. Click on the \"Download\" button after it appears\n6. Click on IMPORT FILE below and select the downloaded zip file\n7. [If the zip import fails] Extract the .csv file (usually under \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), click on IMPORT FILE below and select the extracted csv file</string>
|
||||||
<string name="import_soundcloud_instructions">Import a SoundCloud profile by typing either the URL or your ID:\n\n1. Enable \"desktop mode\" in a web-browser (the site is not available for mobile devices)\n2. Go to this URL: %1$s\n3. Log in when asked\n4. Copy the profile URL you were redirected to.</string>
|
<string name="import_soundcloud_instructions">Import a SoundCloud profile by typing either the URL or your ID:\n\n1. Enable \"desktop mode\" in a web-browser (the site is not available for mobile devices)\n2. Go to this URL: %1$s\n3. Log in when asked\n4. Copy the profile URL you were redirected to.</string>
|
||||||
<string name="import_soundcloud_instructions_hint">yourID, soundcloud.com/yourid</string>
|
<string name="import_soundcloud_instructions_hint">yourID, soundcloud.com/yourid</string>
|
||||||
<string name="import_network_expensive_warning">Keep in mind this operation can be network expensive.\n\nDo you want to continue?</string>
|
<string name="import_network_expensive_warning">Keep in mind this operation can be network expensive.\n\nDo you want to continue?</string>
|
||||||
|
|
Loading…
Reference in New Issue