caronc / apprise

Apprise - Push Notifications that work with just about every platform!
https://hub.docker.com/r/caronc/apprise
BSD 2-Clause "Simplified" License
11k stars 390 forks source link

API for message body limits #778

Open DownrightNifty opened 1 year ago

DownrightNifty commented 1 year ago

Thanks for your work on this library! As described in #198, message length limits are hardcoded for each notification service in the source code and are also posted on the service's wiki page. It would be convenient if there were an API to access this information. You can use the overflow directive to handle the case where messages that are too long (by splitting or truncating the message) but, as mentioned in the documentation, in many cases that doesn't work well and a custom splitting/truncation function is desired.

I think it would make sense to expose this info in the Apprise object's details(). For now, this seems like the best way to get the information (though not ideal because it is accessing private fields):

a = apprise.Apprise.instantiate(service_url)
print(a.body_maxlen)
caronc commented 1 year ago

This isn't an impossible request, at first it seems trivial. The caveat is that services like Twitter have 2 message lengths that change their internal restrictions depending on if we're sending a tweet or a private message.

Some thought would need to go into how it appears in the details() dump.

Basic but Not Intuitive:

I say basic and not intuitive just because of the variance that will come when we're blending these values depending on what variables are set in the URL.

{
    "title_length": 35,
    "body_length": 120
}

Or beyond the case n the case of a text message (no title):

{
    "title_length": 0,
    "body_length": 160
}

But then... Twitter

{
    "title_length": 0,
    "body_length": {
         "mode":  {
              "tweet":  280,
              "private": 5000,
         }
    }
}

The above would imply the variable rate depending on mode=tweet or mode=private

Consistent Response But Added Complexity

Perhaps blend the makes it consistent across the board... Such as

{
    "length": {
           "title": 0,
           "body": 160,
           "type": "fixed",
           "params": {},
    }
}

Then for variable ones like Twitter, we leverage the params. This gives the developer who is adoption Apprise enough details to pass along to the end user the restrictions.

{
    "length": {
           "title": 0,
           "body": null,
           "type": "variable",
           "params": {
               "mode":  {
                     "tweet":  {
                          "body": 280,
                      },
                     "private":  {
                          "body": 5000,
                      }
                }
         }
    }
}

In the above case, the length.title defined value acts as a global. it's passed down into the parameters (in the above case, title would always be 0. The length.body would be defined exclusively the parameters. This last design would give developers enough information to do their own presentation or formatting if needed.

Thoughts?

amotl commented 1 year ago

Hi.

I am not sure if those parameters are implemented within Apprise already. If not, and you will be introducing them in the future, I'd suggest to call them max_title_length and max_body_length, or max_length.*, in order to better reflect their intentions.

With kind regards, Andreas.

DownrightNifty commented 1 year ago

Hmm, I had no idea it was this complicated. I'm not sure what the best way to implement this would be. Perhaps it could simply return the lowest limit? Feel free to close if you don't want to do it! Something like this is still an option:

a = apprise.Apprise.instantiate(service_url)
try:
    max_len = a.body_maxlen
except AttributeError:
    max_len = SOMETHING_REASONABLE
caronc commented 1 year ago

@DownrightNifty i like the idea; will leave ticket open until it's handled 👍

Edit: won't be using lowest value though. The value should correctly pass all options(allowing frontend developers who may use this data too accommodate it all)

joergschultzelutter commented 10 months ago

I was on the verge of suggesting this functionality, too - as I am in the process of finalizing the work on another SMS-based Apprise plugin which you will soon be blessed with as a pull request.

My use case: Send text to multiple devices where some targets CAN digest formatted text, images et al - and others cannot support it (e.g. SMS-based services) AND are heavily restricted in size. I am aware that one cannot create a one-size-fits-all target message where the format will match every messenger that is out there. However, think of the following example:

Obviously, Telegram supports a full-fledged set of formatting rules, images etc. SMS-based services do support plain text only and have a severe restriction in length - which requires two things:

Ultimately, these distinctions are the reason why I had to apply native interfacing to my emergency broadcasting daemon's output generator - rather than using Apprise as one-stop solution.

Maybe it makes sense to think about not just the length that is supported by each plugin BUT also its capabilities - and then allow the user to submit per-flavor message bodies....? Not sure if that is feasible, though.

caronc commented 10 months ago

@joergschultzelutter, i look forward to your merge request.

With respect to this topic: I could keep all of the hardcoded values as they are and just allow them to my overridden on the Apprise URL ?len=3000. Then it eliminates the issue at and, but also invalidates the. API entry discussion here because it can take on any value at this point.

Thoughts to that?

joergschultzelutter commented 10 months ago

@caronc - the development work is already finished and my new plugin works like a charm. However, I need to get this formality resolved before I can issue the pull request - feel free to add a comment to the Github issue and check out the code. The new plugin will enable Apprise to broadcast APRS ham radio messages (similar to my DAPNET plugin).

Related to your suggestion: Yes and no. (My) main issue is that whenever I grant the user the option of creating an Apprise config file that contains a blend of "regular messenger targets" (MS Teams, Telegram, ...) and SMS targets such as DAPNET, those SMS targets will lose the battle as both targets use the same message body.

As Apprise has no separate plain-text-only message body, the only workaround that I can see so far is that I have to instruct the user on configuring TWO Apprise config files where file #1 targets regular messengers and file #2 targets SMS-based messengers. By doing so, I can then submit fitting message bodies for each target type.

Potential alternative wrt buffer length: in order to bypass a SMS messenger's message length limit, you can have a look at this code. tl:dr: submit a text of unlimited length to a SMS-based service and get a list of 1..n messages from it. I haven't included / activated this for both plugins as this might lead to undesired side effects such as transaction costs. I use this muti-message generator with my APRS bot where the text limit is 67 characters but I also need to transmit larger pieces of data.