Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feed problem, some videos do not show up #1130

Open
1 task
EsmailELBoBDev2 opened this issue Jun 14, 2022 · 89 comments
Open
1 task

Feed problem, some videos do not show up #1130

EsmailELBoBDev2 opened this issue Jun 14, 2022 · 89 comments
Labels
bug Something isn't working

Comments

@EsmailELBoBDev2
Copy link

Official Instance

Describe the bug

I self host piped.esmailelbob.xyz and I noticed videos from channels I subbed to in invidious show up and takes so long to show up in piped

To Reproduce

sub to some channels
take channels file
add it to both invidious and piped

Expected behavior

videos show up in my feed when some channel upload a video

Logs/Errors

hmm, not sure what to add here

Browser, and OS with Version.

No response

Additional context

No response

@EsmailELBoBDev2 EsmailELBoBDev2 added the bug Something isn't working label Jun 14, 2022
@FireMasterK
Copy link
Member

Do you have a list of channel IDs that are affected by this bug?

I can check their pubsub subscription status then at https://pubsubhubbub.appspot.com/

@EsmailELBoBDev2
Copy link
Author

EsmailELBoBDev2 commented Jun 28, 2022

I can give you the sub file...
subscriptions.json.txt (had ti change it to .txt for github)

but I noticed something weird, I had problem with my instance I think it was problem with the database, while piped worked okay the login page did not work (pressing on login button did nothing) till I restarted the docker image so I assume it's problem in my own instance, somehow fetchers do not run right?

@FireMasterK
Copy link
Member

This should be fixed with TeamPiped/Piped-Backend@3a00940, let me know if it is not.

@azR-103
Copy link

azR-103 commented Jul 2, 2022

This should be fixed with TeamPiped/Piped-Backend@3a00940, let me know if it is not.

Still have same issue, not all channel feed are being loaded, although i dont have this issue on this custom instance.

https://pipedus.palash.dev

@FireMasterK
Copy link
Member

Still have same issue, not all channel feed are being loaded

Only new videos uploaded from 6 hours back would be updated in the feed, this is due to the nature of how PubSub works.

Let me know if this happens on new uploads from now.

@EsmailELBoBDev2
Copy link
Author

EsmailELBoBDev2 commented Jul 3, 2022

@FireMasterK out of context issue, I noticed piped instance and login (I guess db) sometimes disconnect and I can't login without restart the whole instance so do I need to restart it every hour like invidious?

about feed because what happened, my sync stopped 3 days ago and now I'm waiting it to pull new videos and tell you it worked or no

@EsmailELBoBDev2
Copy link
Author

I have to visit each channel to get new videos in my feed, weird behavior

Is there a command or way to force it to fetch updates from yt?

@EsmailELBoBDev2
Copy link
Author

still do not work, as you see in these pics, in freetube it detected it but in piped I had to visit the channel to make it appear in my feed

Screenshot_20220704_011532
Screenshot_20220704_011559
Screenshot_20220704_011519

@FireMasterK
Copy link
Member

FireMasterK commented Jul 19, 2022

Is there any logs that you can provide? run docker-compose logs piped-backend
The pubsub debug shows that there has been no attempts to subscribe to feed updated for over a month (!!!)
Could you also provide you instance's config.properties file? Just ensure to redact any database information

See: https://pubsubhubbub.appspot.com/subscription-details?hub.callback=https%3A%2F%2Fpipedapi.esmailelbob.xyz%2Fwebhooks%2Fpubsub&hub.topic=https%3A%2F%2Fwww.youtube.com%2Fxml%2Ffeeds%2Fvideos.xml%3Fchannel_id%3DUCadoKaQadkmNZg-MymcKWqg&hub.secret=

@EsmailELBoBDev2
Copy link
Author

EsmailELBoBDev2 commented Jul 20, 2022

Im away from my pc so excuse my werid english

Umm weidly enoguh, i get ERROR: No such service: piped-backend so hmmm

And my config file

# The port to Listen on.
PORT: 8080

# The number of workers to use for the server
HTTP_WORKERS: 2

# Proxy
PROXY_PART: https://pipedproxy.esmailelbob.xyz

# Outgoing HTTP Proxy - eg: 127.0.0.1:8118
#HTTP_PROXY: 127.0.0.1:8118

# Captcha Parameters
CAPTCHA_BASE_URL: https://api.capmonster.cloud/
CAPTCHA_API_KEY: INSERT_HERE

# Public API URL
API_URL: https://pipedapi.esmailelbob.xyz

# Public Frontend URL
FRONTEND_URL: https://piped.esmailelbob.xyz

# Enable haveibeenpwned compromised password API
COMPROMISED_PASSWORD_CHECK: false

# Disable Registration
DISABLE_REGISTRATION: true

# Feed Retention Time in Days
FEED_RETENTION: 30

# Hibernate properties
hibernate.connection.url: jdbc:postgresql://postgres:5432/piped
hibernate.connection.driver_class: org.postgresql.Driver
hibernate.dialect: org.hibernate.dialect.PostgreSQL10Dialect
hibernate.connection.username: piped
hibernate.connection.password: donotchangeme

@FireMasterK
Copy link
Member

Umm weidly enoguh, i get ERROR: No such service: piped-backend so hmmm

Try copying the name of the container from docker ps and replace it in the docker logs command.

@EsmailELBoBDev2
Copy link
Author

Hmm, i have piped backend running but i cant access its logs, it throws same error

@FireMasterK
Copy link
Member

Nvm, you have to run docker logs piped-backend, not docker-compose, my bad!

@EsmailELBoBDev2
Copy link
Author

Ohhhhh 😂

Amyways i cant provide logs as im on phone and cant copy logs and when i send them to commandline pastebin it sends different output

@EsmailELBoBDev2

This comment was marked as outdated.

@KurozyOS
Copy link

I have same issue, I've tried it on official instance and custom one. The subscription won't update until I enter the channel, even if I wait for 6 hours it doesn't update recently. Some videos that are uploaded 20+ hours before don't show.

@FireMasterK
Copy link
Member

Can you share some example channel IDs?

@KurozyOS
Copy link

Here are some:

  • David Bombal
  • ColdFusion
  • DistroTube
  • exurb1a
  • Mental Outlaw
  • the b1m
  • two minute papers
    and much more

@Rekik88
Copy link

Rekik88 commented Sep 11, 2022

I am facing the same problem using the official instance (LinusTechTips NoCopyrightSounds).

Tried different instances and found the same results but with different channels.

However, I've found that some videos does not dissappear but have the wrong time of upload. For example, Linus uploaded a video 15 mins ago but in the feed it shows that it was uploaded 6h ago, when I scroll down the feed I will eventually find it. Maybe this will help.

@NothingCtrl
Copy link

My feed does not update at all, all subscriptions channel only get new video when I visit it directly via Piped UI.

image show feed only showing video 2 days ago
image

My stack installed follow guide: https://piped-docs.kavin.rocks/docs/self-hosting/, using docker method.

This issue just happend recently. Tried rebuild back-end image not fix the issue.

@valynor
Copy link

valynor commented Sep 20, 2022

Can confirm that some of my subbed channels with new videos don't show up in feed, regardless of instance.

One way to make them show up is to go to the channel manually, close the Piped PWA and reopen and voila .. videos for that channel appear in the feed.

Edit: even if you go to the channel manually, the next new video an hour later or so again does not show up. A good example for this is the Netflix channel.

@ghost
Copy link

ghost commented Sep 24, 2022

Can confirm that some of my subbed channels with new videos don't show up in feed, regardless of instance.

One way to make them show up is to go to the channel manually, close the Piped PWA and reopen and voila .. videos for that channel appear in the feed.

Edit: even if you go to the channel manually, the next new video an hour later or so again does not show up. A good example for this is the Netflix channel.

Can confirm the issue is still persistent. I have all the channels bookmarked and when opened at once the new videos show up in feed.

@Donkey-Doug
Copy link

Do you have a list of channel IDs that are affected by this bug?

I can check their pubsub subscription status then at https://pubsubhubbub.appspot.com/

Here are some:

@tron1point0
Copy link

No, that's the whole point of the script - it fetches your list of subscriptions from the DB and does the same request that you do when manually refreshing each subscription individually. You need to use the linked documentation to configure your machine to periodically run the script, which will refresh all subscriptions every time it runs.

@nanedi
Copy link

nanedi commented Mar 18, 2024

@tron1point0

I see.

Thank you

@nanedi
Copy link

nanedi commented Mar 18, 2024

#!/bin/sh
docker exec 08d6366d6b8a \
    psql -Upiped -dpiped -qtAc \
    "SELECT DISTINCT(channel) FROM users_subscribed" | \
    parallel -t -j32 curl -sk -o /dev/null "https://pipedapi.xxxx.com/channel/{}"

I created a CRON script, is this correct? @tron1point0

@nanedi
Copy link

nanedi commented Mar 18, 2024

From your linux machine (where all of your piped dockers are running) you can do this

docker exec <your postgres docker name> psql -U <your database user> -d <your database name> -qtAc "SELECT DISTINCT(channel) FROM users_subscribed" | xargs -d "\n" -P8 -I {} bash -c "curl -sk -o /dev/null 'https://<your piped api url>/channel/{}'"

How is yours different from this one? @dhruvinsh

docker exec 08d6366d6b8a \
    psql -Upiped -dpiped -qtAc \
    "SELECT DISTINCT(channel) FROM users_subscribed" | \
    parallel -t -j32 curl -sk -o /dev/null "https://pipedapi.xxxx.com/channel/{}"

@dhruvinsh
Copy link

Exactly the same just works without parallel and I posted before you got your resolution.

@nanedi
Copy link

nanedi commented Mar 18, 2024

How many channels can be refreshed at the same time?

use CONTAINER ID is ok?

@dhruvinsh

@tron1point0
Copy link

Both xargs and parallel can be configured with as many concurrent jobs as you want, but based on #1130 (comment), I wouldn't try to do more than 50 at a time - youtube might throttle you. The actual limit is somewhere between 32 and 64, but I just don't care enough to find the exact number myself because 32 at a time is plenty for me.

@nanedi
Copy link

nanedi commented Mar 20, 2024

xargs -d "\n" -P8 -I {} bash -c "curl -sk -o /dev/null 'https://<your piped api url>/channel/{}'"

-P8 Is this the number of channels refreshed simultaneously?

How can you verify whether this command has been executed successfully?
Here is no output.

@dhruvinsh

@tron1point0
Copy link

Yes:

       -P max-procs, --max-procs=max-procs
              Run up to max-procs processes at a time; the default is 1.
              If max-procs is 0, xargs will run as many processes as
              possible at a time.

@nanedi
Copy link

nanedi commented Mar 20, 2024

docker exec <your postgres docker name> psql -U <your database user> -d <your database name> -qtAc "SELECT DISTINCT(channel) FROM users_subscribed" | xargs -d "\n" -P8 -I {} bash -c "curl -sk -o /dev/null 'https://<your piped api url>/channel/{}'"

How can you verify whether this command has been executed successfully?
Here is no output.

@tron1point0

@tron1point0
Copy link

If executed correctly with parallel, you would see something like the following on STDOUT (in your terminal):

curl -sk -o /dev/null https://[...redacted...]/channel/[...redacted...]
curl -sk -o /dev/null https://[...redacted...]/channel/[...redacted...]
curl -sk -o /dev/null https://[...redacted...]/channel/[...redacted...]
curl -sk -o /dev/null https://[...redacted...]/channel/[...redacted...]
...

Where the first [...redacted...] in each line is the same as the value of $PIPED_API_URL and the second [...redacted...] is a youtube channel ID, like UCX6OQ3DkcsbYNE6H8uQQuVA.

Don't forget to replace <your postgres docker name> (and the other placeholders) with the appropriate values in the command.

@nanedi
Copy link

nanedi commented Mar 20, 2024

If executed correctly with parallel, you would see something like the following on STDOUT (in your terminal):

curl -sk -o /dev/null https://[...redacted...]/channel/[...redacted...]
curl -sk -o /dev/null https://[...redacted...]/channel/[...redacted...]
curl -sk -o /dev/null https://[...redacted...]/channel/[...redacted...]
curl -sk -o /dev/null https://[...redacted...]/channel/[...redacted...]
...

Where the first [...redacted...] in each line is the same as the value of $PIPED_API_URL and the second [...redacted...] is a youtube channel ID, like UCX6OQ3DkcsbYNE6H8uQQuVA.

Don't forget to replace <your postgres docker name> (and the other placeholders) with the appropriate values in the command.

I use xargs.

@tron1point0
Copy link

Then you can drop the -s ("silent") flag from the curl command so it shows a progress indicator, like so:

$ docker exec piped_postgres_1 psql -Upiped -dpiped -qtAc "SELECT DISTINCT(channel) FROM users_subscribed" | xargs -I\{} curl -k -o /dev/null 'https://[...redacted...]/channel/{}'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2607  100  2607    0     0   166k      0 --:--:-- --:--:-- --:--:--  181k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2607  100  2607    0     0   215k      0 --:--:-- --:--:-- --:--:--  231k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
...

@IngwiePhoenix
Copy link

I ran the script above (albeit modified, I use k3s) and the feed still is not updated.

Any other way I can solve this?

# kubectl exec -n postgres pods/default-cluster-1 -c postgres -- psql -Upostgres -d piped -qtAc "SELECT DISTINCT(channel) FROM users_subscribed" | wc -l
768

This number also shows up in the logs:

Jan 06, 2025 8:26:23 PM liquibase.database
INFO: Set default schema name to public
Jan 06, 2025 8:26:24 PM liquibase.changelog
INFO: Reading from public.databasechangelog
Database is up to date, no changesets to execute
Jan 06, 2025 8:26:24 PM liquibase.changelog
INFO: Reading from public.databasechangelog

UPDATE SUMMARY
Run:                          0
Previously run:               3
Filtered out:                 1
-------------------------------
Total change sets:            4


FILTERED CHANGE SETS SUMMARY
DBMS mismatch:                1

Jan 06, 2025 8:26:24 PM liquibase.util
INFO: UPDATE SUMMARY
Jan 06, 2025 8:26:24 PM liquibase.util
INFO: Run:                          0
Jan 06, 2025 8:26:24 PM liquibase.util
INFO: Previously run:               3
Jan 06, 2025 8:26:24 PM liquibase.util
INFO: Filtered out:                 1
Jan 06, 2025 8:26:24 PM liquibase.util
INFO: -------------------------------
Jan 06, 2025 8:26:24 PM liquibase.util
INFO: Total change sets:            4
Jan 06, 2025 8:26:24 PM liquibase.util
INFO: FILTERED CHANGE SETS SUMMARY
Jan 06, 2025 8:26:24 PM liquibase.util
INFO: DBMS mismatch:                1
Jan 06, 2025 8:26:24 PM liquibase.util
INFO: Update summary generated
Jan 06, 2025 8:26:24 PM liquibase.lockservice
INFO: Successfully released change log lock
Jan 06, 2025 8:26:24 PM liquibase.command
INFO: Command execution complete
ThrottlingCache: 0 entries
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
Jan 06, 2025 8:26:25 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version [WORKING]
Jan 06, 2025 8:26:26 PM org.hibernate.cache.internal.RegionFactoryInitiator initiateService
INFO: HHH000026: Second-level cache disabled
Logged in as user: null
Room ID: !CfXSiQMnWTEPfnBNuK:matrix.org
Filter ID: null
Jan 06, 2025 8:26:35 PM org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator initiateService
INFO: HHH000130: Instantiating explicit connection provider: org.hibernate.hikaricp.internal.HikariCPConnectionProvider
Jan 06, 2025 8:26:39 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl constructDialect
WARN: HHH90000025: PostgreSQLDialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
Jan 06, 2025 8:26:44 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
Database connection is ready!
Cleanup: Removed 0 old videos
PubSub: queue size - 763 channels
ThrottlingCache: 0 entries
Cleanup: Removed 0 old videos
PubSub: queue size - 763 channels
ThrottlingCache: 0 entries
Cleanup: Removed 0 old videos
(...)
PubSub: queue size - 763 channels
Failed to subscribe: 429
Throttled.
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
        at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2648)
        at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:685)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2750)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
        at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4934)
        at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3260)
        at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:36)
        at me.kavin.piped.utils.matrix.SyncRunner.run(SyncRunner.java:97)
        at java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
java.lang.RuntimeException: Failed to parse JSON
        at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:40)
        at me.kavin.piped.utils.matrix.SyncRunner.run(SyncRunner.java:97)
        at java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
        at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2648)
        at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:685)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2750)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
        at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4934)
        at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3260)
        at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:36)
        ... 2 more
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
        at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2648)
        at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:685)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2750)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
        at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4934)
        at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3260)
        at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:36)
        at me.kavin.piped.utils.matrix.SyncRunner.run(SyncRunner.java:97)
        at java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
java.lang.RuntimeException: Failed to parse JSON
        at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:40)
        at me.kavin.piped.utils.matrix.SyncRunner.run(SyncRunner.java:97)
        at java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
        at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2648)
        at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:685)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2750)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
        at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
        at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4934)
        at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3260)
        at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:36)
        ... 2 more
ThrottlingCache: 0 entries
Cleanup: Removed 0 old videos
PubSub: queue size - 763 channels
ThrottlingCache: 0 entries
Cleanup: Removed 2 old videos
ThrottlingCache: 0 entries
(...)
Cleanup: Removed 0 old videos
PubSub: queue size - 764 channels
ThrottlingCache: 0 entries
Cleanup: Removed 0 old videos
PubSub: queue size - 765 channels
ThrottlingCache: 0 entries
Cleanup: Removed 0 old videos
ThrottlingCache: 0 entries
Cleanup: Removed 0 old videos
PubSub: queue size - 765 channels

@0xF4CED
Copy link

0xF4CED commented Jan 8, 2025

Here is a much improved script to do this.
It does not hammer the API with new HTTP handshakes for every channel.
It requests all channels in one HTTP session, and the server can decide how fast it will respond/process them.
Also, it does not request the content of each endpoint/channel but only asks for status information, further reducing load.

I have noticed that the piped API now takes exactly 1 second for every channel/request, which has not been the case previously.
Is this a new rate limiting feature of piped, or is it youtubes rate limiting @FireMasterK?

#!/bin/bash

PIPEDAPI="https://pipedapi.example.com"

curl -LIsfZkw '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' --retry 1 --config \
  <(docker exec -i piped-postgres \
    bash -c "PGPASSWORD=\$POSTGRES_PASSWORD psql -U \$POSTGRES_USER -d \$POSTGRES_DB -qtAXc \
    \"SELECT DISTINCT 'url=\"$PIPEDAPI\"/channel/' || id FROM public.pubsub;\"") \
  >/dev/null

@PhrozenByte
Copy link

@TeamPiped Since there seems to be a stable, scriptable workaround and since a proper fix is pending for 2,5 years now, could this workaround be included in the official Docker image, so that all Piped instances benefit from it?

The issue wasn't that serious 2,5 years ago because it only affected few videos, but since YouTube's war against adblockers and 3rd-party apps it became a permanent condition that renders Piped's subscription feature basically useless. This also affects popular dependant projects like LibreTube. Including this workaround into the official images would be very much appreciated.

@tron1point0
Copy link

#!/bin/bash

PIPEDAPI="https://pipedapi.example.com"

SUBS=$(docker exec -i piped-postgres \
  bash -c "PGPASSWORD=\$POSTGRES_PASSWORD psql -U \$POSTGRES_USER -d \$POSTGRES_DB -qtAX -c \"select '\"$PIPEDAPI\"/channel/' || id from public.pubsub;\"")

curl -LIsfZkw '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' --retry 1 $SUBS >/dev/null

Nice! I golfed that a little differently to pass the URLs to curl via --config on STDIN because the total length of the command line is limited:

docker exec $PIPED_CONTAINER \
    psql -U$PIPED_DB_USER -d$PIPED_DB_NAME -qtAc \
    "SELECT DISTINCT(channel) FROM users_subscribed" | \
    sed "s_^_url = $PIPED_API_URL/channel/_" | \
    curl -LIsfZ -r 1 -C - -w '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' \
    >/dev/null

The sed could also be removed to make psql do all the string munging, but I find this pipeline clearer.

@0xF4CED
Copy link

0xF4CED commented Jan 11, 2025

could this workaround be included in the official Docker image, so that all Piped instances benefit from it?

The problem is, that this is more of a hack than a proper workaround; It does not scale and is very inefficient as it queries every channel that is in the db every time, even if they have no new content for years.
The proper way would be getting an announcement from youtube for new content like piped intended to do with pubsub.

So this hacky workaround is fine for your private piped instances, but for big public instances it's kind of unfeasible, unfortunately. (Especially with the 1 sec per channel rate limiting)
It could be added to the documentation, though.

I have further improved the script:

  • Using only subscribed channels instead of all pubsub entries
  • passing the URLs as config file to curl to prevent Argument list too long error
    Thanks @tron1point0

Also, if it wasn't clear already, the script expands the env variables that are already present in the postgres container, so no need to pass them to the script.

#!/bin/bash

PIPEDAPI="https://pipedapi.example.com"

curl -LIsfZkw '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' --retry 1 --config \
  <(docker exec -i piped-postgres \
    bash -c "PGPASSWORD=\$POSTGRES_PASSWORD psql -U \$POSTGRES_USER -d \$POSTGRES_DB -qtAXc \
    \"SELECT DISTINCT 'url=\"$PIPEDAPI\"/channel/' || channel FROM users_subscribed;\"") \
  >/dev/null

@PhrozenByte
Copy link

The problem is, that this is more of a hack than a proper workaround; It does not scale and is very inefficient as it queries every channel that is in the db every time, even if they have no new content for years.
The proper way would be getting an announcement from youtube for new content like piped intended to do with pubsub.

I'd say every workaround is a hack, that's what distinguishes it from a proper fix 😄

The problem is that this issue persists for 2,5 years now and it seems like that nobody is either able (this includes myself), or willing to invest the time necessary to develop a proper fix, or it really can't be fixed in a meaningful way. I don't know and honestly, I don't think the reasons matter in the end. Since subscriptions is one of Piped's key features, I'd consider its breakage (and let's be honest, it's completely broken) major enough to justify a workaround until a proper fix is found and merged. That's just my IMHO though.

So this hacky workaround is fine for your private piped instances, but for big public instances it's kind of unfeasible, unfortunately. (Especially with the 1 sec per channel rate limiting)

Since it's a workaround, downsides - even major ones - are expected. Workarounds are temporary solutions after all. The question is whether the workaround stays feasible.

Working with a rate limit doesn't really prevent us from applying this workaround, but only how many channels we can process in a given time. So for example, if users of a given instance have subscribed to 21,600 unique channels, feeds can only be updated four times a day max. I can only speak for myself here, but I'd definitely prefer having a feed with a 6 hour delay instead of having no working feed at all.

I don't run a public Piped instance, so I can't really assess about how many unique channels we're talking for larger instances. For example, kavin.rocks has 421,150 registered users. It's unlikely that subscriptions don't overlap, but I guess we still end up with way too many unique channels on kavin.rocks. So, this workaround likely isn't feasible for kavin.rocks, at least not until rate limit evasion measures are taken. The two next largest instances (adminforge.de and drgns.space) have 23,367 and 13,979 registered users respectively. I can only speculate, but I would be surprised (considering what I know now, there definitely could be obstacles I just don't know, please tell me then) if we can't at least get daily updates (= 86,400 unique channels max) with this workaround on these instances. Smaller instances should be fine and allow for more than one feed update per day.

So, let's work on improving the workaround to make it more feasible for instances of any size and ready to be included in the official Docker images.

First we need a config option to enable/disable this workaround. This could be as simple as adding a Docker env variable. Second we can't leave calling this script up to a cronjob, because we don't know whether the number of unique channels exceeds the number of channels we can process in the cronjob's frequency. On the other hand we don't want to update channels too often. So, let's modify the script so that it runs repeatedly indefinitely and pauses if it has processed all channels before the next run is due. The frequency should be configurable, too (let's start with hourly updates).

Here's a proof-of-concept with these two additions:

#!/bin/bash
PIPEDAPI="https://pipedapi.example.com"
SUBSCRIPTIONS_WORKAROUND_ENABLED="${SUBSCRIPTIONS_WORKAROUND_ENABLED:-1}"
SUBSCRIPTIONS_WORKAROUND_FREQUENCY="${SUBSCRIPTIONS_WORKAROUND_FREQUENCY:-3600}"

if [ "$SUBSCRIPTIONS_WORKAROUND_ENABLED" == "1" ]; then
    while true; do
        sleep_until=$(($(date +%s) + SUBSCRIPTIONS_WORKAROUND_FREQUENCY))
        curl -LIsfZkw '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' --retry 1 --config \
            <(docker exec -i piped-postgres \
                bash -c "PGPASSWORD=\$POSTGRES_PASSWORD psql -U \$POSTGRES_USER -d \$POSTGRES_DB -qtAXc \
                \"SELECT DISTINCT 'url=\"$PIPEDAPI\"/channel/' || channel FROM users_subscribed;\"") \
            >/dev/null
        (( $(date +%s) >= sleep_until )) || sleep $(( sleep_until - $(date +%s) ))
    done
fi

It still remains a rather simple workaround. That's by design, if it gets too complex it would be better to either develop a proper fix or at least include the workaround directly into Piped instead of calling Piped's API with curl. However, we're not at this point yet.

So, let's discuss a few more possible additions. You mentioned that it doesn't make much sense to update channels that don't publish videos that frequently. I absolutely agree. A simple solution could be to actually add two workaround scripts: One frequent version that excludes channels without recent videos (that's as simple as using a different SQL query), and another less frequently running version that only updates the channels excluded by the first one. This two-tier system could also include other criteria, for example channels that don't have many subscribers could fall into the low-frequency tier, or could be excluded completely (e.g. if there's just one subscriber). The criteria could be configurable, so that admins can choose what fits their instance best. WDYT?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests