Merge branch 'release/3.29.0'

This commit is contained in:
JackDandy 2023-05-22 00:28:06 +01:00
commit 930b5ed533
604 changed files with 148531 additions and 8342 deletions

View file

@ -15,7 +15,7 @@ jobs:
matrix: matrix:
os: os:
- windows-latest - windows-latest
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] python-version: ['3.8', '3.9', '3.10', '3.11']
steps: steps:
- name: 'Set up Python ${{ matrix.python-version }}' - name: 'Set up Python ${{ matrix.python-version }}'
uses: actions/setup-python@v4 uses: actions/setup-python@v4
@ -34,7 +34,7 @@ jobs:
matrix: matrix:
os: os:
- ubuntu-latest - ubuntu-latest
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] python-version: ['3.8', '3.9', '3.10', '3.11']
steps: steps:
- name: 'Set up Python ${{ matrix.python-version }}' - name: 'Set up Python ${{ matrix.python-version }}'
uses: actions/setup-python@v4 uses: actions/setup-python@v4
@ -55,7 +55,7 @@ jobs:
matrix: matrix:
os: os:
- macos-latest - macos-latest
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] python-version: ['3.8', '3.9', '3.10', '3.11']
steps: steps:
- name: 'Set up Python ${{ matrix.python-version }}' - name: 'Set up Python ${{ matrix.python-version }}'
uses: actions/setup-python@v4 uses: actions/setup-python@v4

View file

@ -1,4 +1,35 @@
### 3.28.0 (2023-04-12 13:05:00 UTC) ### 3.29.0 (2023-05-22 00:25:00 UTC)
* Change minimum required Python to version 3.8
* Update Apprise 1.2.1 (3d07004) to 1.3.0 (6458ab0)
* Update attr 22.2.0 (a9960de) to 22.2.0 (683d056)
* Update certifi 2022.12.07 to 2023.05.07
* Update diskcache 5.4.0 (1cb1425) to 5.6.1 (4d30686)
* Update feedparser 6.0.10 (5fcb3ae) to 6.0.10 (6d032b8)
* Update filelock 3.9.0 (ce3e891) to 3.12.0 (b4713c9)
* Update Msgpack 1.0.4 (b5acfd5) to 1.0.5 (0516c2c)
* Update Pytvmaze library 2.0.8 (16ed096) to 2.0.8 (81888a5)
* Update Requests library 2.28.1 (ec553c2) to 2.29.0 (87d63de)
* Update Send2Trash 1.8.1b0 (0ef9b32) to 1.8.2 (0244f53)
* Update SimpleJSON 3.18.1 (c891b95) to 3.19.1 (aeb63ee)
* Update Tornado Web Server 6.3.0 (7186b86) to 6.3.2 (e3aa6c5)
* Update urllib3 1.26.14 (a06c05c) to 1.26.15 (25cca389)
* Remove singledispatch
* Change allow rapidfuzz update from 2.x.x to 3.x.x
* Change remove redundant py2 import futures
* Change add jobs to centralise scheduler activities
* Change refactor scene_exceptions
* Add to config/media-process/File Handling, "Rename TBA" and "Rename any"
* Add config to change media process log message if there is no media to process
* Change view-show text "invalid timeformat" to "time unknown"
* Add menu Shows/"TMDB Cards"
* Add a persons available socials (Youtube, LinkedIn, Reddit, Fansite, TikTok, Wikidata)
* Change use TVDb genres on view-show if config/General/Interface/"Enable IMDb info" is disabled
* Fix TVDb api episode issues
* Change remove Python 3.7 from CI
### 3.28.0 (2023-04-12 13:05:00 UTC)
* Update html5lib 1.1 (f87487a) to 1.2-dev (3e500bb) * Update html5lib 1.1 (f87487a) to 1.2-dev (3e500bb)
* Update package resource API 63.2.0 (3ae44cd) to 67.5.1 (f51eccd) * Update package resource API 63.2.0 (3ae44cd) to 67.5.1 (f51eccd)

View file

@ -17,6 +17,7 @@ Libs with customisations...
/lib/hachoir_parser/guess.py /lib/hachoir_parser/guess.py
/lib/hachoir_parser/misc/torrent.py /lib/hachoir_parser/misc/torrent.py
/lib/imdbpie /lib/imdbpie
/lib/language_data/names.py
/lib/lockfile/mkdirlockfile.py /lib/lockfile/mkdirlockfile.py
/lib/rtorrent /lib/rtorrent
/lib/scandir/scandir.py /lib/scandir/scandir.py

View file

@ -15,7 +15,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with SickGear. If not, see <http://www.gnu.org/licenses/>. # along with SickGear. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
from time import sleep from time import sleep
import runpy import runpy
print( print(

View file

@ -1312,6 +1312,9 @@ div.formpaginate{
width:480px; width:480px;
margin-top:0 margin-top:0
} }
#addShowForm #nameToSearch.select2{
width:428px;
}
#addShowForm #nameToSearch.wide{ #addShowForm #nameToSearch.wide{
width:591px; width:591px;
} }
@ -1439,12 +1442,16 @@ home_browseShows.tmpl
padding-top:2px padding-top:2px
} }
.show-card-inner .rating{
margin-right:3px;
}
.show-card-inner .heart.icon-glyph{ .show-card-inner .heart.icon-glyph{
display:inline-block; display:inline-block;
float:none; float:none;
height:15px; height:15px;
width:15px; width:15px;
margin:0 -3px -2px 2px margin:0 -3px -2px -1px
} }
.show-card-inner p, .show-card-inner i{ .show-card-inner p, .show-card-inner i{
@ -3786,6 +3793,13 @@ option.flag{
background-position:10px 50% background-position:10px 50%
} }
#select2-infosrc-lang-select-container .flag,
#select2-infosrc-lang-select-results .flag{
padding-left:25px;
background-repeat:no-repeat;
background-position:0 50%
}
/* Anime section for editShow */ /* Anime section for editShow */
.anigrouplists-wrapper{ .anigrouplists-wrapper{
height:auto; height:auto;

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 B

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

View file

@ -77,7 +77,7 @@ def param(visible=True, rid=None, cache_person=None, cache_char=None, person=Non
#elif $PersonGenders.male == $cur_person.gender# #elif $PersonGenders.male == $cur_person.gender#
#set $gender = 'himself' #set $gender = 'himself'
#end if# #end if#
#set $name = ($cur_person.name, $gender)[$rc_clean.sub('', $cur_person.name.lower()) == $rc_clean.sub('', $character.name.lower())] #set $name = ($cur_person.name, $gender)[$rc_clean.sub('', $cur_person.name.lower()) == $rc_clean.sub('', ($character.name or 'unknown name').lower())]
<a href="$sbRoot/home/person?$param(person=$cur_person)">$name</a>#if 2 <= $num_people and $cur_enum + 1 == $num_people# and #elif 2 < $num_people and $cur_enum < $num_people#<span>, </span>#end if# <a href="$sbRoot/home/person?$param(person=$cur_person)">$name</a>#if 2 <= $num_people and $cur_enum + 1 == $num_people# and #elif 2 < $num_people and $cur_enum < $num_people#<span>, </span>#end if#
#end for #end for
</div> </div>

View file

@ -85,7 +85,7 @@
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="process_automatically" id="process_automatically" #if $sickgear.PROCESS_AUTOMATICALLY == True then $checked else ''#> <input type="checkbox" name="process_automatically" id="process_automatically" #if $sickgear.PROCESS_AUTOMATICALLY == True then $checked else ''#>
<p>files in the <em>completed TV downloads</em> folder</p> <p>files in the <em>completed TV downloads</em> folder</p>
<p class="clear-left note"><b>note:</b> do not enable with external post processing scripts like sabTosickgear for SABnzbd, or NZBMedia for NZBGET</p> <p class="clear-left note"><b>note:</b> do not enable with external post processing scripts like sabTosickgear for SABnzbd, or NZBMedia for NZBGET unless you're an expert</p>
</span> </span>
</label> </label>
</div> </div>
@ -109,6 +109,17 @@
</span> </span>
</label> </label>
</div> </div>
<div class="field-pair">
<label for="process_positive_log">
<span class="component-title">If no media to process</span>
<span class="component-desc">
<input type="checkbox" name="process_positive_log" id="process_positive_log" #if $sickgear.PROCESS_POSITIVE_LOG then $checked else ''#>
<p>use positive log message "<i class="grey-text">Success, no media to process.</i>"</p>
<p class="clear-left note">some setups require the old warning "<i class="grey-text">Failed! Did not process any files.</i>"</p>
</span>
</label>
</div>
#if False: #if False:
""" """
<div class="field-pair"> <div class="field-pair">
@ -231,10 +242,30 @@
<div class="field-pair"> <div class="field-pair">
<label for="rename_episodes"> <label for="rename_episodes">
<span class="component-title">Rename episodes</span> <span class="component-title">Rename episode files</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="rename_episodes" id="rename_episodes" #if $sickgear.RENAME_EPISODES == True then $checked else ''#> <input type="checkbox" name="rename_episodes" id="rename_episodes" #if $sickgear.RENAME_EPISODES == True then $checked else ''#>
<p>rename episodes using the Episode Naming settings</p> <p>using the Episode Naming settings</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="rename_tba_episodes">
<span class="component-title">Rename "TBA" named files</span>
<span class="component-desc">
<input type="checkbox" name="rename_tba_episodes" id="rename_tba_episodes" #if $sickgear.RENAME_TBA_EPISODES == True then $checked else ''#>
<p>if the TV info episode name changes</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="rename_name_changed_episodes">
<span class="component-title">Rename any named file</span>
<span class="component-desc">
<input type="checkbox" name="rename_name_changed_episodes" id="rename_name_changed_episodes" #if $sickgear.RENAME_NAME_CHANGED_EPISODES == True then $checked else ''#>
<p>if the TV info episode name changes</p>
</span> </span>
</label> </label>
</div> </div>

View file

@ -113,10 +113,7 @@
<div class="clearfix" style="margin-bottom:15px"></div> <div class="clearfix" style="margin-bottom:15px"></div>
#if $show_message #if $show_message
<div class="alert alert-info"> <div class="alert alert-info">$show_message</div>
$show_message
</div>
#end if #end if
<div class="display-show-container"> <div class="display-show-container">
<div id="posterCol" class="hidden-xs"> <div id="posterCol" class="hidden-xs">
@ -179,6 +176,9 @@
#if not $genres_done and $show_obj.genre #if not $genres_done and $show_obj.genre
#for $genre in $show_obj.genre.split('|') #for $genre in $show_obj.genre.split('|')
#set $genres_done = True #set $genres_done = True
#if $TVINFO_TVDB == $show_obj.tvid
#set $genre = '<a href="%s" target="_blank" title="View other popular %s shows on thetvdb.com" class="addQTip">%s</a>' % (anon_url('https://thetvdb.com/genres/', $genre), $genre, $genre)
#end if
<span class="label">$genre</span> <span class="label">$genre</span>
#end for# #end for#
#end if #end if
@ -278,7 +278,7 @@
#if $show_obj.airs #if $show_obj.airs
#set $showairs = '%s%s' % ($re.sub(r'(?:s|nes|rs|ur)?day', '', $re.sub(r'(y)[^\w]+', r'\1, ', $show_obj.airs)), #set $showairs = '%s%s' % ($re.sub(r'(?:s|nes|rs|ur)?day', '', $re.sub(r'(y)[^\w]+', r'\1, ', $show_obj.airs)),
('', ' <span class="red-text" style="font-weight:bold">(invalid timeformat)</span>')[not $network_timezones.test_timeformat($show_obj.airs)]) ('', ' <span class="red-text" style="font-weight:bold">(time unknown)</span>')[not $network_timezones.test_timeformat($show_obj.airs)])
#set $showairs = $showairs.replace('Sat, Sun', 'Sat - Sun').replace('Mon, Tue, Wed, Thu, Fri', 'Mon - Fri').replace('Mon, Tue, Wed, Thu', 'Mon - Thu').replace('Tue, Wed, Thu', 'Tue - Thu') #set $showairs = $showairs.replace('Sat, Sun', 'Sat - Sun').replace('Mon, Tue, Wed, Thu, Fri', 'Mon - Fri').replace('Mon, Tue, Wed, Thu', 'Mon - Thu').replace('Tue, Wed, Thu', 'Tue - Thu')
<div> <div>
<span class="details-title">Air#echo ('s', 'ed')[$show_ended]#</span> <span class="details-title">Air#echo ('s', 'ed')[$show_ended]#</span>

View file

@ -28,6 +28,24 @@
<script type="text/javascript" src="$sbRoot/js/qualityChooser.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/qualityChooser.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/editShow.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/editShow.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/livepanel.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/livepanel.js?v=$sbPID"></script>
<script src="$sbRoot/js/lib/select2.full.min.js"></script>
<link href="$sbRoot/css/lib/select2.css" rel="stylesheet">
<style>
.select2-container{height:32px; font-size:12px; margin-right:6px}
.select2-container .select2-selection--single{height:30px}
.select2-results__group{color: #eee; background-color: rgb(51,51,51)}
.select2-results__options .select2-results__option{color: #222; background-color: #ddd}
.select2-results__options .select2-results__option .ended{color: #888}
.select2-container--default .select2-results > .select2-results__options{max-height: 300px}
#select2-infosrc-lang-select-results .select2-results__option,
#select2-infosrc-lang-select-results .select2-results__group{padding-top: 2px !important; padding-bottom:2px !important}
#select2-infosrc-lang-select-results .select2-results__option--highlighted.select2-results__option--selectable .ended{color:white}
#select2-infosrc-lang-select-results .select2-results__option--selected,
#select2-infosrc-lang-select-results .select2-results__option--selected span{color:rgb(143, 21, 21) !important}
#select2-infosrc-lang-select-results span.flag{width:100%; height:100%; display:block}
</style>
#if $varExists('header') #if $varExists('header')
<h1 class="header"><span class="grey-text">Edit&nbsp;</span>$header</h1> <h1 class="header"><span class="grey-text">Edit&nbsp;</span>$header</h1>
#else #else
@ -244,10 +262,10 @@
</div> </div>
<div class="field-pair"> <div class="field-pair">
<label for="infosrc-lang-select-edit"> <label for="infosrc-lang-select">
<span class="component-title">Info language</span> <span class="component-title">Info language</span>
<span class="component-desc"> <span class="component-desc">
<select name="tvinfo_lang" id="infosrc-lang-select-edit" class="form-control form-control-inline input-sm"></select> <select name="tvinfo_lang" id="infosrc-lang-select" class="form-control form-control-inline input-sm"></select>
<span>fetch show information in this language</span> <span>fetch show information in this language</span>
</span> </span>
</label> </label>

View file

@ -186,9 +186,7 @@
<div class="bfr"><img src="$sbRoot/images/loading16${theme_suffix}.gif"><img src="$sbRoot/images/loading16-red.gif"><img src="$sbRoot/images/queued.png"><img src="$sbRoot/images/search16.png"><img src="$sbRoot/images/no16.png"><img src="$sbRoot/images/yes16.png"></div> <div class="bfr"><img src="$sbRoot/images/loading16${theme_suffix}.gif"><img src="$sbRoot/images/loading16-red.gif"><img src="$sbRoot/images/queued.png"><img src="$sbRoot/images/search16.png"><img src="$sbRoot/images/no16.png"><img src="$sbRoot/images/yes16.png"></div>
#if $show_message #if $show_message
<div class="alert alert-info" style="margin:-40px 0 50px"> <div class="alert alert-info" style="margin:-40px 0 50px">$show_message</div>
$show_message
</div>
#end if #end if
#if $varExists('header') #if $varExists('header')

View file

@ -10,8 +10,10 @@
#set $mode = $kwargs and $kwargs.get('mode', '') #set $mode = $kwargs and $kwargs.get('mode', '')
#set $use_network = $kwargs.get('use_networks', False) #set $use_network = $kwargs.get('use_networks', False)
#set $use_returning = 'returning' == mode #set $use_returning = 'returning' == mode
#set $use_votes = $kwargs and $kwargs.get('use_votes', True) #set $use_filter = $kwargs and $kwargs.get('use_filter', True)
#set $use_ratings = $kwargs and $kwargs.get('use_ratings', True) #set $use_ratings = $kwargs and $kwargs.get('use_ratings', True)
#set $use_votes = $kwargs and $kwargs.get('use_votes', True)
#set $term_vote = $kwargs and $kwargs.get('term_vote', 'Votes')
## ##
#set global $title='Browse %s Shows' % $browse_type #set global $title='Browse %s Shows' % $browse_type
#set global $header='Browse Shows' #set global $header='Browse Shows'
@ -236,7 +238,8 @@ $(document).ready(function(){
$('#showfilter').on('change', function(){ $('#showfilter').on('change', function(){
var filterValue = this.value; var filterValue = this.value;
if (-1 == filterValue.indexOf('trakt') && -1 == filterValue.indexOf('imdb') && -1 == filterValue.indexOf('mc_') if (-1 == filterValue.indexOf('trakt') && -1 == filterValue.indexOf('imdb') && -1 == filterValue.indexOf('mc_')
&& -1 == filterValue.indexOf('tvc_') && -1 == filterValue.indexOf('tvm_') && -1 == filterValue.indexOf('tmdb_') && -1 == filterValue.indexOf('tvc_')
&& -1 == filterValue.indexOf('tvm_')
&& -1 == filterValue.indexOf('ne_') && -1 == filterValue.indexOf('_ne') && -1 == filterValue.indexOf('ne_') && -1 == filterValue.indexOf('_ne')
&& -1 == filterValue.indexOf('default')) { && -1 == filterValue.indexOf('default')) {
var el$ = $('#container') var el$ = $('#container')
@ -322,16 +325,16 @@ $(document).ready(function(){
</optgroup> </optgroup>
<optgroup label="Sort by"> <optgroup label="Sort by">
<option value="by_name"#if 'by_name' in $saved_showsort_sortby and not $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Name</option> <option value="by_name"#if 'by_name' in $saved_showsort_sortby and not $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Name</option>
## omit for TVMaze as original order == First Aired ## omit for TVMaze as original order == First Aired
#if 'TVmaze' not in $browse_type #if 'TVmaze' not in $browse_type
<option value="by_order"#if 'by_order' in $saved_showsort_sortby or $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Original</option> <option value="by_order"#if 'by_order' in $saved_showsort_sortby or $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Original</option>
#end if #end if
<option value="by_premiered"#if 'by_premiered' in $saved_showsort_sortby and not $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#First aired</option> <option value="by_premiered"#if 'by_premiered' in $saved_showsort_sortby and not $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#First aired</option>
#if $use_returning #if $use_returning
<option value="by_returning"#if 'by_returning' in $saved_showsort_sortby and not $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Returning</option> <option value="by_returning"#if 'by_returning' in $saved_showsort_sortby and not $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Returning</option>
#end if #end if
#if $use_votes #if $use_votes
<option value="by_votes"#if 'by_votes' in $saved_showsort_sortby#$selected>>&nbsp;#else#>#end if#Votes</option> <option value="by_votes"#if 'by_votes' in $saved_showsort_sortby#$selected>>&nbsp;#else#>#end if#$term_vote</option>
#end if #end if
#if $use_ratings #if $use_ratings
<option value="by_rating"#if 'by_rating' in $saved_showsort_sortby#$selected>>&nbsp;#else#>#end if#% Rating</option> <option value="by_rating"#if 'by_rating' in $saved_showsort_sortby#$selected>>&nbsp;#else#>#end if#% Rating</option>
@ -342,13 +345,13 @@ $(document).ready(function(){
</optgroup> </optgroup>
</select> </select>
#if 'Ani' not in $browse_type #if 'Ani' not in $browse_type and $use_filter
<select id="showfilter" class="form-control form-control-inline input-sm"> <select id="showfilter" class="form-control form-control-inline input-sm">
#set $selected = ' class="selected" selected="selected"' #set $selected = ' class="selected" selected="selected"'
#if 'Trakt' == $browse_type #if 'Trakt' == $browse_type
<optgroup label="Trakt"> <optgroup label="Trakt">
<option value="trakt_anticipated"#echo ('', selected)['anticipated' == $mode]#>Anticipating</option> <option value="trakt_anticipated"#echo ('', selected)['anticipated' == $mode]#>Anticipating</option>
<option value="trakt_newseasons"#echo ('', selected)['newseasons' == $mode]#>New Seasons</option> <option value="trakt_newseasons"#echo ('', selected)['returning' == $mode]#>New Seasons</option>
<option value="trakt_newshows"#echo ('', selected)['newshows' == $mode]#>New Shows</option> <option value="trakt_newshows"#echo ('', selected)['newshows' == $mode]#>New Shows</option>
<option value="trakt_popular"#echo ('', selected)['popular' == $mode]#>Popular</option> <option value="trakt_popular"#echo ('', selected)['popular' == $mode]#>Popular</option>
<option value="trakt_trending"#echo ('', selected)['trending' == $mode]#>Trending</option> <option value="trakt_trending"#echo ('', selected)['trending' == $mode]#>Trending</option>
@ -423,6 +426,14 @@ $(document).ready(function(){
<option value="mc_newseries?more=1"#echo ('', selected + ' disabled')[mode.endswith('more')]#>... list more</option> <option value="mc_newseries?more=1"#echo ('', selected + ' disabled')[mode.endswith('more')]#>... list more</option>
#end if #end if
</optgroup> </optgroup>
#elif 'TMDB' == $browse_type
<optgroup label="TMDB">
<option value="tmdb_upcoming"#echo ('', selected)['upcoming' == $mode]#>Upcoming</option>
<option value="tmdb_popular"#echo ('', selected)['popular' == $mode]#>Popular</option>
<option value="tmdb_toprated"#echo ('', selected)['toprated' == $mode]#>Top rated</option>
<option value="tmdb_trending_today"#echo ('', selected)['trending_today' == $mode]#>Trending today</option>
<option value="tmdb_trending_week"#echo ('', selected)['trending_week' == $mode]#>Trending this week</option>
</optgroup>
#elif 'TVCalendar' == $browse_type #elif 'TVCalendar' == $browse_type
<optgroup label="TVCalendar"> <optgroup label="TVCalendar">
#for $page in $kwargs.get('pages') or [] #for $page in $kwargs.get('pages') or []
@ -466,10 +477,10 @@ $(document).ready(function(){
#set $poster_id += 1 #set $poster_id += 1
#set $title_html = $this_show['title'].replace('"', '&quot;').replace("'", '&#39;') #set $title_html = $this_show['title'].replace('"', '&quot;').replace("'", '&#39;')
#if 'newseasons' == $mode #if 'returning' == $mode
#set $overview = '%s: %s' % ( #set $overview = '%s: %s' % (
('Season %s' % $this_show['episode_season'], 'Brand-new')[1 == $this_show['episode_season']], 'Season %s' % $this_show['episode_season'],
($this_show['overview'], $this_show['episode_overview'])[any($this_show['episode_overview']) and 1 != $this_show['episode_season']]) $this_show['episode_overview'] or $this_show['overview'])
#else #else
#set $overview = $this_show['overview'] #set $overview = $this_show['overview']
#end if #end if
@ -477,16 +488,18 @@ $(document).ready(function(){
#set $show_id = $this_show.get('show_id') #set $show_id = $this_show.get('show_id')
#set $known = ('not', '')[bool($this_show.get('indb'))] #set $known = ('not', '')[bool($this_show.get('indb'))]
#set $hide = ('', '%shide ' % ('', 'to-')['.hide' in $saved_showsort_view])[bool($this_show.get('hide'))] #set $hide = ('', '%shide ' % ('', 'to-')['.hide' in $saved_showsort_view])[bool($this_show.get('hide'))]
#if $use_ratings:
#set $data_rating = $try_float($this_show['rating']) #set $data_rating = $try_float($this_show['rating'])
#end if
<div class="show-card ${hide}${known}inlibrary" data-name="#echo re.sub(r'([\'\"])', r'', $this_show['title'])#" data_id="$show_id"#if $use_ratings# data-rating="$data_rating"#end if##if $use_votes# data-votes="$this_show['votes']"#end if# data-premiered="$this_show['premiered']"#if $use_returning# data-returning="$this_show['returning']"#end if# data-order="$this_show['order']"#if $use_network# data-network="$this_show['network']"#end if#> <div class="show-card ${hide}${known}inlibrary" data-name="#echo re.sub(r'([\'\"])', r'', $this_show['title'])#" data_id="$show_id"#if $use_ratings# data-rating="$data_rating"#end if##if $use_votes# data-votes="$this_show['votes']"#end if# data-premiered="$this_show['ord_premiered']"#if $use_returning# data-returning="$this_show['ord_returning']"#end if# data-order="$this_show['order']"#if $use_network# data-network="$this_show['network']"#end if#>
<div class="show-card-inner"> <div class="show-card-inner">
<div class="browse-image"> <div class="browse-image">
<a class="browse-image" href="<%= anon_url(this_show['url_src_db']) %>" target="_blank" <a class="browse-image" href="<%= anon_url(this_show['url_src_db']) %>" target="_blank"
title="<span style='color: rgb(66, 139, 202)'>$re.sub(r'(?m)\s+\((?:19|20)\d\d\)\s*$', '', $title_html)</span> title="<span style='color: rgb(66, 139, 202)'>$re.sub(r'(?m)\s+\((?:19|20)\d\d\)\s*$', '', $title_html)</span>
#if $this_show['genres']#<br><div style='font-weight:bold'>(<em>$this_show['genres']</em>)</div>#end if# #if $this_show['genres']#<br><div style='font-weight:bold'>(<em>$this_show['genres']</em>)</div>#end if#
#if $kwargs and $use_returning#<span style='display:block;clear:both;font-weight:bold;font-size:0.9em;color:#888'><em>Season $this_show['episode_season'] returns $this_show['returning_str']</em></span>#end if# #if $kwargs and $use_returning#<span style='display:block;clear:both;font-weight:bold;font-size:0.9em;color:#888'><em>Season $this_show['episode_season'] return#echo ('s', 'ed')[$this_show['return_past']]# $this_show['str_returning']</em></span>#end if#
#if $this_show.get('country') or $this_show.get('language') #if $this_show.get('country') or $this_show.get('language')
<p style='line-height:15px;margin-bottom:2px'> <p style='line-height:15px;margin-bottom:2px'>
#if $this_show.get('country') #if $this_show.get('country')
@ -498,7 +511,7 @@ $(document).ready(function(){
</p> </p>
#end if #end if
<p style='margin:0 0 2px'>#echo re.sub(r'([,\.!][^,\.!]*?)$', '...', re.sub(r'([!\?\.])(?=\w)', r'\1 ', $overview)).replace('.....', '...')#</p> <p style='margin:0 0 2px'>#echo re.sub(r'([,\.!][^,\.!]*?)$', '...', re.sub(r'([!\?\.])(?=\w)', r'\1 ', $overview)).replace('.....', '...')#</p>
<p>#if $this_show['premiered_str']#<span style='font-weight:bold;font-size:0.9em;color:#888'><em>#if $kwargs and 'newseasons' == $mode#Air#else#First air#end if##echo ('s', 'ed')[$this_show['when_past']]#: $this_show['premiered_str']</em></span>#end if# <p>#if $this_show['str_premiered']#<span style='font-weight:bold;font-size:0.9em;color:#888'><em>#if 'Trakt' == $browse_type and $kwargs and 'returning' == $mode#Air#else#First air#end if##echo ('s', 'ed')[$this_show['started_past']]#: $this_show['str_premiered']</em></span>#end if#
#if $this_show.get('ended_str')# - <span style='font-weight:bold;font-size:0.9em;color:#888'><em>Ended: $this_show['ended_str']</em></span>#end if# #if $this_show.get('ended_str')# - <span style='font-weight:bold;font-size:0.9em;color:#888'><em>Ended: $this_show['ended_str']</em></span>#end if#
#if $this_show.get('network')#<span style='display:block;clear:both;font-weight:bold;font-size:0.9em;color:#888'><em>On: $this_show['network']</em></span>#end if# #if $this_show.get('network')#<span style='display:block;clear:both;font-weight:bold;font-size:0.9em;color:#888'><em>On: $this_show['network']</em></span>#end if#
</p> </p>
@ -521,7 +534,7 @@ $(document).ready(function(){
#end if #end if
<div class="clearfix"> <div class="clearfix">
#if $use_ratings or $use_votes #if $use_ratings or $use_votes
<p>#if $use_ratings#$this_show['rating']#if $re.search(r'^\d+(\.\d+)?$', (str($this_show['rating'])))#%#end if##end if##if $use_votes#<i class="heart icon-glyph"></i><i>$this_show['votes'] votes</i>#end if#</p>#slurp# <p>#if $use_ratings#<span class="rating">$this_show['rating']#if $re.search(r'^\d+(\.\d+)?$', (str($this_show['rating'])))#%</span>#end if##end if##if $use_votes#<i class="heart icon-glyph"></i><i>$this_show['votes'] $term_vote.lower()</i>#end if#</p>#slurp#
#end if #end if
#if 'url_tvdb' in $this_show and $this_show['url_tvdb'] #if 'url_tvdb' in $this_show and $this_show['url_tvdb']
<a class="service" href="<%= anon_url(this_show['url_tvdb']) %>" onclick="window.open(this.href, '_blank'); return false;" <a class="service" href="<%= anon_url(this_show['url_tvdb']) %>" onclick="window.open(this.href, '_blank'); return false;"
@ -539,7 +552,7 @@ $(document).ready(function(){
</div> </div>
</div> </div>
<div class="ui-progressbar ui-widget ui-widget-content ui-corner-all"> <div class="ui-progressbar ui-widget ui-widget-content ui-corner-all">
#set $state = 'progress-%s0" title="%s"' % (('2', 'Upcoming'), ('8', 'Started'))[$this_show['when_past']] #set $state = 'progress-%s0" title="%s"' % (('2', 'Upcoming'), ('8', 'Started'))[$this_show['started_past']]
<div style="width:102%" class="ui-progressbar-value ui-widget-header ui-corner-left ui-corner-right $state></div> <div style="width:102%" class="ui-progressbar-value ui-widget-header ui-corner-left ui-corner-right $state></div>
</div> </div>
</div> </div>

View file

@ -35,6 +35,23 @@
<script type="text/javascript" src="$sbRoot/js/qualityChooser.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/qualityChooser.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/newShow.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/newShow.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/addShowOptions.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/addShowOptions.js?v=$sbPID"></script>
<script src="$sbRoot/js/lib/select2.full.min.js"></script>
<link href="$sbRoot/css/lib/select2.css" rel="stylesheet">
<style>
.select2-container{height:32px; font-size:12px}
.select2-container .select2-selection--single{height:30px}
.select2-results__group{color: #eee; background-color: rgb(51,51,51)}
.select2-results__options .select2-results__option{color: #222; background-color: #ddd}
.select2-results__options .select2-results__option .ended{color: #888}
.select2-container--default .select2-results > .select2-results__options{max-height: 300px}
#select2-infosrc-lang-select-results .select2-results__option,
#select2-infosrc-lang-select-results .select2-results__group{padding-top: 2px !important; padding-bottom:2px !important}
#select2-infosrc-lang-select-results .select2-results__option--highlighted.select2-results__option--selectable .ended{color:white}
#select2-infosrc-lang-select-results .select2-results__option--selected,
#select2-infosrc-lang-select-results .select2-results__option--selected span{color:rgb(143, 21, 21) !important}
#select2-infosrc-lang-select-results span.flag{width:100%; height:100%; display:block}
</style>
#if $varExists('header') #if $varExists('header')
<h1 class="header">$header</h1> <h1 class="header">$header</h1>

View file

@ -1,5 +1,6 @@
#import sickgear #import sickgear
#import datetime #import datetime
#import re
#import urllib #import urllib
#from sickgear.common import Quality, SNATCHED_ANY, DOWNLOADED, ARCHIVED, FAILED #from sickgear.common import Quality, SNATCHED_ANY, DOWNLOADED, ARCHIVED, FAILED
#from sickgear.helpers import anon_url #from sickgear.helpers import anon_url
@ -176,10 +177,29 @@
<li><a id="add-show-name" data-href="$sbRoot/add-shows/find/" tabindex="$tab#set $tab += 1#"><i class="sgicon-addshow"></i> <li><a id="add-show-name" data-href="$sbRoot/add-shows/find/" tabindex="$tab#set $tab += 1#"><i class="sgicon-addshow"></i>
<input class="form-control form-control-inline input-sm" type="text" placeholder="Search" tabindex="$tab#set $tab += 1#"> <input class="form-control form-control-inline input-sm" type="text" placeholder="Search" tabindex="$tab#set $tab += 1#">
<div class="menu-item-desc opacity60">find show at TV info source</div></a></li> <div class="menu-item-desc opacity60">find show at TV info source</div></a></li>
#set $tvm_modes = dict(tvm_premieres='new shows', tvm_returning='returning')
#set $tvm_mode = $tvm_modes.get($sg_var('TVM_MRU'), 'new shows')
<li><a href="$sbRoot/add-shows/tvm-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-tvmaze"></i>TVmaze Cards
<div class="menu-item-desc opacity60">$tvm_mode...</div></a></li>
#set $tmdb_modes = dict(tmdb_upcoming='upcoming', tmdb_popular='popular', tmdb_toprated='top rated', tmdb_trending_today='trending today', tmdb_trending_week='trending this week')
#set $tmdb_mode = $tmdb_modes.get($sg_var('TMDB_MRU'), 'upcoming')
<li><a href="$sbRoot/add-shows/tmdb-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-addshow"></i>TMDB Cards
<div class="menu-item-desc opacity60">$tmdb_mode...</div></a></li>
#set $trakt_modes = dict(trakt_anticipated='anticipated', trakt_returning='returning', trakt_newshows='premieres', trakt_popular='popular', trakt_trending='trending',
trakt_watched='most watched this month', trakt_watched_period_year='most watched this year',
trakt_played='most played this month', trakt_played_period_year='most played this year',
trakt_collected='most collected this month', trakt_collected_period_year='most collected this year',
trakt_recommended='recommended', trakt_watchlist='watchlist')
#set $trakt_mode = $trakt_modes.get(re.sub('[\?=]', '_', $sg_var('TRAKT_MRU')), 'trends, tailored suggestions')
<li><a href="$sbRoot/add-shows/trakt-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-trakt"></i>Trakt Cards <li><a href="$sbRoot/add-shows/trakt-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-trakt"></i>Trakt Cards
<div class="menu-item-desc opacity60">trends, tailored suggestions...</div></a></li> <div class="menu-item-desc opacity60">$trakt_mode...</div></a></li>
#set $imdb_func = $sg_str('IMDB_MRU').split('-')
#set $imdb_mru, $params = ($imdb_func[0], '') if 2 > len($imdb_func) else $imdb_func
#set $period = ('', ' %s' % $params.replace(',', ' to '))['popular' == $imdb_mru]
#set $imdb_modes = dict(popular='popular', watchlist='watchlist')
#set $imdb_mode = $imdb_modes.get($imdb_mru, 'popular decades, watchlists...')
<li><a href="$sbRoot/add-shows/imdb-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-imdb"></i>IMDb Cards <li><a href="$sbRoot/add-shows/imdb-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-imdb"></i>IMDb Cards
<div class="menu-item-desc opacity60">popular decades, watchlists...</div></a></li> <div class="menu-item-desc opacity60">$imdb_mode$period...</div></a></li>
#set $mc_modes = dict(mc_90days='last 90 days', mc_year='by year', mc_discussed='most discussed', mc_shared='most shared') #set $mc_modes = dict(mc_90days='last 90 days', mc_year='by year', mc_discussed='most discussed', mc_shared='most shared')
#set $mc_mode = $mc_modes.get($sg_var('MC_MRU'), 'new seasons') #set $mc_mode = $mc_modes.get($sg_var('MC_MRU'), 'new seasons')
<li><a href="$sbRoot/add-shows/mc-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-metac"></i>Metacritic Cards <li><a href="$sbRoot/add-shows/mc-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-metac"></i>Metacritic Cards
@ -188,10 +208,6 @@
#set $tvc_mode = $tvc_modes.get($sg_var('TVC_MRU'), 'new shows') #set $tvc_mode = $tvc_modes.get($sg_var('TVC_MRU'), 'new shows')
<li><a href="$sbRoot/add-shows/tvc-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-tvc"></i>TV Calendar Cards <li><a href="$sbRoot/add-shows/tvc-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-tvc"></i>TV Calendar Cards
<div class="menu-item-desc opacity60">$tvc_mode...</div></a></li> <div class="menu-item-desc opacity60">$tvc_mode...</div></a></li>
#set $tvm_modes = dict(tvm_premieres='new shows', tvm_returning='returning')
#set $tvm_mode = $tvm_modes.get($sg_var('TVM_MRU'), 'new shows')
<li><a href="$sbRoot/add-shows/tvm-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-tvmaze"></i>TVmaze Cards
<div class="menu-item-desc opacity60">$tvm_mode...</div></a></li>
#set $ne_modes = dict(ne_newpop='new popular', ne_newtop='new top rated', ne_upcoming='upcoming', ne_trending='trending') #set $ne_modes = dict(ne_newpop='new popular', ne_newtop='new top rated', ne_upcoming='upcoming', ne_trending='trending')
#set $ne_mode = $ne_modes.get($sg_var('NE_MRU'), 'new popular') #set $ne_mode = $ne_modes.get($sg_var('NE_MRU'), 'new popular')
<li><a href="$sbRoot/add-shows/ne-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-ne"></i>Next Episode Cards <li><a href="$sbRoot/add-shows/ne-default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-ne"></i>Next Episode Cards

View file

@ -16,31 +16,73 @@ $(document).ready(function () {
return ' class="flag" style="background-image:url(' + $.SickGear.Root + '/images/flags/' + lang + '.png)"' return ' class="flag" style="background-image:url(' + $.SickGear.Root + '/images/flags/' + lang + '.png)"'
} }
$.getJSON($.SickGear.Root + '/add-shows/get-infosrc-languages', {}, function (data) { function uriFlag(lang) {
var result = '', currentLangAdded = '', selected = ' selected="selected"'; return $.SickGear.Root + '/images/flags/' + lang + '.png'
}
if (!data.results.length) { $.getJSON($.SickGear.Root + '/add-shows/get-infosrc-languages', {}, function (data) {
result = '<option value="' + config.showLang + '"' + selected + htmlFlag(config.showLang) + '>' var htmlText = '', currentLangAdded = '',
selected = ' selected="selected"', htmlSelected = '',
elInfosrcLang = $('#infosrc-lang-select'),
useSelect2 = 0 < data.results_ext.length, populateItem;
if (!data.results.length && !data.results_ext.length) {
htmlText = '<option value="' + config.showLang + '"' + selected + htmlFlag(config.showLang) + '>'
+ config.showLang + '</option>'; + config.showLang + '</option>';
} else { } else {
currentLangAdded = !1; currentLangAdded = !1;
if (useSelect2){
// 3 letter abbr object
$.each(data.results_ext, function (index, obj) {
htmlSelected = '';
if (obj.std_abbr === config.showLang) {
currentLangAdded = !0;
htmlSelected = selected;
}
htmlText += '<option style="padding-left:25px" value="' + obj.std_abbr + '"'
+ ' data-abbr="' + obj.abbr + '"'
+ ' data-img="' + uriFlag(obj.std_abbr) + '"'
+ ' data-title="' + obj.en + ' (' + obj.orig_abbr + '/' + obj.std_abbr + '/' + obj.abbr + ')' + '"'
+ (!!htmlSelected
? htmlSelected + '>&gt; '
: '>')
+ obj.native
+ '</option>';
});
} else {
// legacy 2 letter abbr list
$.each(data.results, function (index, strLang) { $.each(data.results, function (index, strLang) {
var htmlSelected = ''; htmlSelected = '';
if (strLang === config.showLang) { if (strLang === config.showLang) {
currentLangAdded = !0; currentLangAdded = !0;
htmlSelected = selected; htmlSelected = selected;
} }
result += '<option value="' + strLang + '"' + htmlSelected + htmlFlag(strLang) + '>' htmlText += '<option value="' + strLang + '"' + htmlSelected + htmlFlag(strLang) + '>'
+ strLang + '</option>'; + strLang + '</option>';
}); });
}
if (!currentLangAdded) if (!currentLangAdded)
result += '<option value="' + config.showLang + '" ' + selected + '>' + config.showLang + '</option>'; htmlText += '<option value="' + config.showLang + '" ' + selected + '>' + config.showLang + '</option>';
} }
$('#infosrc-lang-select-edit').html(result); elInfosrcLang.html(htmlText);
if (useSelect2) {
populateItem = function (data) {
if (!!data.element)
return $('<span class="flag"'
+ ' style="background-image:url(' + $(data.element).data('img') + ')"'
+ ' title="' + $(data.element).data('title') + '">'
+ data.text
+ '</span>');
return data.text;
}
elInfosrcLang.select2({templateResult: populateItem, templateSelection: populateItem, width: 162});
}
}); });
function getExceptions() { function getExceptions() {

View file

@ -9,6 +9,10 @@ $(document).ready(function () {
return ' class="flag" style="background-image:url(' + $.SickGear.Root + '/images/flags/' + lang + '.png)"' return ' class="flag" style="background-image:url(' + $.SickGear.Root + '/images/flags/' + lang + '.png)"'
} }
function uriFlag(lang) {
return $.SickGear.Root + '/images/flags/' + lang + '.png'
}
function populateLangSelect() { function populateLangSelect() {
if (!$('#nameToSearch').length) if (!$('#nameToSearch').length)
return; return;
@ -17,27 +21,58 @@ $(document).ready(function () {
$.getJSON(sbRoot + '/add-shows/get-infosrc-languages', {}, function (data) { $.getJSON(sbRoot + '/add-shows/get-infosrc-languages', {}, function (data) {
var resultStr = '', flag, var htmlText = '', flag,
selected = ' selected="selected"', selected = ' selected="selected"',
elInfosrcLang = $('#infosrc-lang-select'); elInfosrcLang = $('#infosrc-lang-select'),
useSelect2 = 0 < data.results_ext.length, populateItem;
if (0 === data.results.length) { if (0 === data.results.length && 0 === data.results_ext.length) {
resultStr = '<option value="en"' + selected + '>&gt; en</option>'; htmlText = '<option value="en"' + selected + '>&gt; en</option>';
} else { } else {
if (useSelect2) {
$('#nameToSearch').addClass('select2');
// 3 letter abbr object
$.each(data.results_ext, function (index, obj) {
htmlText += '<option style="padding-left:25px" value="' + obj.std_abbr + '"'
+ ' data-abbr="' + obj.abbr + '"'
+ ' data-img="' + uriFlag(obj.std_abbr) + '"'
+ ' data-title="' + obj.en + ' (' + obj.orig_abbr + '/' + obj.std_abbr + '/' + obj.abbr + ')' + '"'
+ ('' === htmlText
? selected + '>&gt; '
: '>')
+ obj.native
+ '</option>';
});
} else {
// legacy 2 letter abbr list
$.each(data.results, function (index, obj) { $.each(data.results, function (index, obj) {
flag = htmlFlag(obj); flag = htmlFlag(obj);
resultStr += '<option value="' + obj + '"' htmlText += '<option value="' + obj + '"'
+ ('' === resultStr + ('' === htmlText
? flag.replace('"flag', '"flag selected-text') + selected + '>&gt; ' ? flag.replace('"flag', '"flag selected-text') + selected + '>&gt; '
: flag + '>') : flag + '>')
+ obj + '</option>'; + obj + '</option>';
}); });
} }
}
elInfosrcLang.html(resultStr); elInfosrcLang.html(htmlText);
elInfosrcLang.change(function () { elInfosrcLang.change(function () {
searchIndexers(); searchIndexers();
}); });
if (useSelect2) {
populateItem = function(data) {
if (!!data.element)
return $('<span class="flag"'
+ ' style="background-image:url(' + $(data.element).data('img') + ')"'
+ ' title="' + $(data.element).data('title') + '">'
+ data.text
+ '</span>');
return data.text;
}
elInfosrcLang.select2({templateResult: populateItem, templateSelection: populateItem, width: 155});
}
}); });
} }
} }

View file

@ -13,15 +13,20 @@ import re
from bs4_parser import BS4Parser from bs4_parser import BS4Parser
from exceptions_helper import ex from exceptions_helper import ex
from lib import imdbpie from lib import imdbpie
# from lib.tvinfo_base.exceptions import BaseTVinfoShownotfound
from lib.tvinfo_base import PersonGenders, TVInfoBase, TVInfoIDs, TVInfoCharacter, TVInfoPerson, TVInfoShow, \
TVINFO_IMDB
# , TVINFO_TMDB, TVINFO_TRAKT, TVINFO_TVDB, TVINFO_TVRAGE, \
# TVINFO_FACEBOOK, TVINFO_INSTAGRAM, TVINFO_TWITTER, TVINFO_WIKIPEDIA
from lib.dateutil.parser import parser from lib.dateutil.parser import parser
from sg_helpers import get_url, try_int # from lib.tvinfo_base.exceptions import BaseTVinfoShownotfound
from lib.tvinfo_base import (
TVInfoCharacter, TVInfoPerson, PersonGenders, TVINFO_IMDB,
# TVINFO_FACEBOOK, TVINFO_INSTAGRAM, TVINFO_TMDB, TVINFO_TRAKT,
# TVINFO_TVDB, TVINFO_TVRAGE, TVINFO_TWITTER, TVINFO_WIKIPEDIA,
TVInfoBase, TVInfoIDs, TVInfoShow)
from sg_helpers import clean_data, enforce_type, get_url, try_int
from json_helper import json_loads
from six import iteritems from six import iteritems
from six.moves import http_client as httplib
from six.moves.urllib.parse import urlencode, urljoin, quote, unquote
# noinspection PyUnreachableCode # noinspection PyUnreachableCode
if False: if False:
@ -33,6 +38,37 @@ log = logging.getLogger('imdb.api')
log.addHandler(logging.NullHandler()) log.addHandler(logging.NullHandler())
def _get_imdb(self, url, query=None, params=None):
headers = {'Accept-Language': self.locale}
if params:
full_url = '{0}?{1}'.format(url, urlencode(params))
else:
full_url = url
headers.update(self.get_auth_headers(full_url))
resp = get_url(url, headers=headers, params=params, return_response=True)
if not resp.ok:
if resp.status_code == httplib.NOT_FOUND:
raise LookupError('Resource {0} not found'.format(url))
else:
msg = '{0} {1}'.format(resp.status_code, resp.text)
raise imdbpie.ImdbAPIError(msg)
resp_data = resp.content.decode('utf-8')
try:
resp_dict = json_loads(resp_data)
except ValueError:
resp_dict = self._parse_dirty_json(
data=resp_data, query=query
)
if resp_dict.get('error'):
return None
return resp_dict
imdbpie.Imdb._get = _get_imdb
class IMDbIndexer(TVInfoBase): class IMDbIndexer(TVInfoBase):
# supported_id_searches = [TVINFO_IMDB] # supported_id_searches = [TVINFO_IMDB]
supported_person_id_searches = [TVINFO_IMDB] supported_person_id_searches = [TVINFO_IMDB]
@ -67,12 +103,13 @@ class IMDbIndexer(TVInfoBase):
""" """
def _make_result_dict(s): def _make_result_dict(s):
imdb_id = try_int(re.search(r'tt(\d+)', s.get('id') or s.get('imdb_id')).group(1), None) imdb_id = try_int(re.search(r'tt(\d+)', s.get('id') or s.get('imdb_id')).group(1), None)
tvs = TVInfoShow() ti_show = TVInfoShow()
tvs.seriesname, tvs.id, tvs.firstaired, tvs.genre_list, tvs.overview, tvs.poster, tvs.ids = \ ti_show.seriesname, ti_show.id, ti_show.firstaired, ti_show.genre_list, ti_show.overview, \
s['title'], imdb_id, s.get('releaseDetails', {}).get('date') or s.get('year'), s.get('genres'), \ ti_show.poster, ti_show.ids = \
s.get('plot', {}).get('outline', {}).get('text'), s.get('image') and s['image'].get('url'), \ clean_data(s['title']), imdb_id, s.get('releaseDetails', {}).get('date') or s.get('year'), \
TVInfoIDs(imdb=imdb_id) s.get('genres'), enforce_type(clean_data(s.get('plot', {}).get('outline', {}).get('text')), str, ''), \
return tvs s.get('image') and s['image'].get('url'), TVInfoIDs(imdb=imdb_id)
return ti_show
results = [] results = []
if ids: if ids:
@ -106,20 +143,20 @@ class IMDbIndexer(TVInfoBase):
def _convert_person(person_obj, filmography=None, bio=None): def _convert_person(person_obj, filmography=None, bio=None):
if isinstance(person_obj, dict) and 'imdb_id' in person_obj: if isinstance(person_obj, dict) and 'imdb_id' in person_obj:
imdb_id = try_int(re.search(r'(\d+)', person_obj['imdb_id']).group(1)) imdb_id = try_int(re.search(r'(\d+)', person_obj['imdb_id']).group(1))
return TVInfoPerson(p_id=imdb_id, name=person_obj['name'], ids={TVINFO_IMDB: imdb_id}) return TVInfoPerson(p_id=imdb_id, name=person_obj['name'], ids=TVInfoIDs(ids={TVINFO_IMDB: imdb_id}))
characters = [] characters = []
for known_for in (filmography and filmography['filmography']) or []: for known_for in (filmography and filmography['filmography']) or []:
if known_for['titleType'] not in ('tvSeries', 'tvMiniSeries'): if known_for['titleType'] not in ('tvSeries', 'tvMiniSeries'):
continue continue
for character in known_for.get('characters') or []: for character in known_for.get('characters') or ['unknown name']:
show = TVInfoShow() ti_show = TVInfoShow()
show.id = try_int(re.search(r'(\d+)', known_for.get('id')).group(1)) ti_show.id = try_int(re.search(r'(\d+)', known_for.get('id')).group(1))
show.ids.imdb = show.id ti_show.ids.imdb = ti_show.id
show.seriesname = known_for.get('title') ti_show.seriesname = known_for.get('title')
show.firstaired = known_for.get('year') ti_show.firstaired = known_for.get('year')
characters.append( characters.append(
TVInfoCharacter(name=character, show=show, TVInfoCharacter(name=character, ti_show=ti_show, start_year=known_for.get('startYear'),
start_year=known_for.get('startYear'), end_year=known_for.get('endYear')) end_year=known_for.get('endYear'))
) )
try: try:
birthdate = person_obj['base']['birthDate'] and tz_p.parse(person_obj['base']['birthDate']).date() birthdate = person_obj['base']['birthDate'] and tz_p.parse(person_obj['base']['birthDate']).date()
@ -131,7 +168,7 @@ class IMDbIndexer(TVInfoBase):
deathdate = None deathdate = None
imdb_id = try_int(re.search(r'(\d+)', person_obj['id']).group(1)) imdb_id = try_int(re.search(r'(\d+)', person_obj['id']).group(1))
return TVInfoPerson( return TVInfoPerson(
p_id=imdb_id, ids={TVINFO_IMDB: imdb_id}, characters=characters, p_id=imdb_id, ids=TVInfoIDs(ids={TVINFO_IMDB: imdb_id}), characters=characters,
name=person_obj['base'].get('name'), real_name=person_obj['base'].get('realName'), name=person_obj['base'].get('name'), real_name=person_obj['base'].get('realName'),
nicknames=set((person_obj['base'].get('nicknames') and person_obj['base'].get('nicknames')) or []), nicknames=set((person_obj['base'].get('nicknames') and person_obj['base'].get('nicknames')) or []),
akas=set((person_obj['base'].get('akas') and person_obj['base'].get('akas')) or []), akas=set((person_obj['base'].get('akas') and person_obj['base'].get('akas')) or []),
@ -175,7 +212,8 @@ class IMDbIndexer(TVInfoBase):
results.append(self._convert_person(cp)) results.append(self._convert_person(cp))
return results return results
def _get_bio(self, p_id): @staticmethod
def _get_bio(p_id):
try: try:
bio = get_url('https://www.imdb.com/name/nm%07d/bio' % p_id, headers={'Accept-Language': 'en'}) bio = get_url('https://www.imdb.com/name/nm%07d/bio' % p_id, headers={'Accept-Language': 'en'})
if not bio: if not bio:
@ -217,4 +255,3 @@ class IMDbIndexer(TVInfoBase):
self._set_cache_entry(cache_credits_key, fg) self._set_cache_entry(cache_credits_key, fg)
if p: if p:
return self._convert_person(p, filmography=fg, bio=bio) return self._convert_person(p, filmography=fg, bio=bio)

View file

@ -1,7 +1,6 @@
# encoding:utf-8 # encoding:utf-8
# author:Prinz23 # author:Prinz23
# project:tmdb_api # project:tmdb_api
from __future__ import division
__author__ = 'Prinz23' __author__ = 'Prinz23'
__version__ = '1.0' __version__ = '1.0'
@ -9,6 +8,7 @@ __api_version__ = '1.0.0'
import datetime import datetime
import logging import logging
import re
from lib import tmdbsimple from lib import tmdbsimple
from lib.dateutil.parser import parser from lib.dateutil.parser import parser
@ -19,13 +19,13 @@ from lib.tvinfo_base import CastList, PersonGenders, RoleTypes, \
TVINFO_IMDB, TVINFO_TMDB, TVINFO_TVDB, \ TVINFO_IMDB, TVINFO_TMDB, TVINFO_TVDB, \
TVINFO_FACEBOOK, TVINFO_INSTAGRAM, TVINFO_TWITTER TVINFO_FACEBOOK, TVINFO_INSTAGRAM, TVINFO_TWITTER
from json_helper import json_dumps from json_helper import json_dumps
from sg_helpers import clean_data, get_url, iterate_chunk, try_int from sg_helpers import clean_data, enforce_type, get_url, iterate_chunk, try_int
from six import iteritems from six import iteritems
# noinspection PyUnreachableCode # noinspection PyUnreachableCode
if False: if False:
from typing import Any, AnyStr, Dict, List, Optional from typing import Any, AnyStr, Dict, List, Optional, Union
from six import integer_types from six import integer_types
log = logging.getLogger('tmdb.api') log = logging.getLogger('tmdb.api')
@ -180,17 +180,19 @@ class TmdbIndexer(TVInfoBase):
self.size_map = response.get('size_map') self.size_map = response.get('size_map')
self.tv_genres = response.get('genres') self.tv_genres = response.get('genres')
def _search_show(self, name=None, ids=None, **kwargs): def _search_show(self, name=None, ids=None, lang=None, **kwargs):
# type: (AnyStr, Dict[integer_types, integer_types], Optional[Any]) -> List[TVInfoShow] # type: (Union[AnyStr, List[AnyStr]], Dict[integer_types, integer_types], Optional[string_types], Optional[Any]) -> List[Dict]
"""This searches TMDB for the series name, """This searches TMDB for the series name,
""" """
tmdb_lang = ('en-US', lang)[lang in self._tmdb_supported_lang_list]
def _make_result_dict(s): def _make_result_dict(s):
tvs = TVInfoShow() ti_show = TVInfoShow()
tvs.seriesname, tvs.id, tvs.seriesid, tvs.firstaired, tvs.genre_list, tvs.overview, tvs.poster, tvs.ids, \ ti_show.seriesname, ti_show.id, ti_show.seriesid, ti_show.firstaired, ti_show.genre_list, \
tvs.language, tvs.popularity, tvs.rating = \ ti_show.overview, ti_show.poster, ti_show.ids, ti_show.language, ti_show.popularity, ti_show.rating = \
clean_data(s['name']), s['id'], s['id'], clean_data(s.get('first_air_date')) or None, \ clean_data(s['name']), s['id'], s['id'], clean_data(s.get('first_air_date')) or None, \
clean_data([self.tv_genres.get(g) for g in s.get('genre_ids') or []]), \ clean_data([self.tv_genres.get(g) for g in s.get('genre_ids') or []]), \
clean_data(s.get('overview')), s.get('poster_path') and '%s%s%s' % ( self._enforce_text(s.get('overview')), s.get('poster_path') and '%s%s%s' % (
self.img_base_url, self.size_map[TVInfoImageType.poster][TVInfoImageSize.original], self.img_base_url, self.size_map[TVInfoImageType.poster][TVInfoImageSize.original],
s.get('poster_path')), \ s.get('poster_path')), \
TVInfoIDs(tvdb=s.get('external_ids') and s['external_ids'].get('tvdb_id'), TVInfoIDs(tvdb=s.get('external_ids') and s['external_ids'].get('tvdb_id'),
@ -198,8 +200,8 @@ class TmdbIndexer(TVInfoBase):
imdb=s.get('external_ids') and s['external_ids'].get('imdb_id') and imdb=s.get('external_ids') and s['external_ids'].get('imdb_id') and
try_int(s['external_ids'].get('imdb_id', '').replace('tt', ''), None)), \ try_int(s['external_ids'].get('imdb_id', '').replace('tt', ''), None)), \
clean_data(s.get('original_language')), s.get('popularity'), s.get('vote_average') clean_data(s.get('original_language')), s.get('popularity'), s.get('vote_average')
tvs.genre = '|'.join(tvs.genre_list or []) ti_show.genre = '|'.join(ti_show.genre_list or [])
return tvs return ti_show
results = [] results = []
if ids: if ids:
@ -210,7 +212,7 @@ class TmdbIndexer(TVInfoBase):
is_none, shows = self._get_cache_entry(cache_id_key) is_none, shows = self._get_cache_entry(cache_id_key)
if not self.config.get('cache_search') or (None is shows and not is_none): if not self.config.get('cache_search') or (None is shows and not is_none):
try: try:
show = tmdbsimple.TV(id=p).info(append_to_response='external_ids') show = tmdbsimple.TV(id=p).info(append_to_response='external_ids', language=tmdb_lang)
except (BaseException, Exception): except (BaseException, Exception):
continue continue
self._set_cache_entry(cache_id_key, show, expire=self.search_cache_expire) self._set_cache_entry(cache_id_key, show, expire=self.search_cache_expire)
@ -224,10 +226,10 @@ class TmdbIndexer(TVInfoBase):
if not self.config.get('cache_search') or (None is shows and not is_none): if not self.config.get('cache_search') or (None is shows and not is_none):
try: try:
show = tmdbsimple.Find(id=(p, 'tt%07d' % p)[t == TVINFO_IMDB]).info( show = tmdbsimple.Find(id=(p, 'tt%07d' % p)[t == TVINFO_IMDB]).info(
external_source=id_map[t]) external_source=id_map[t], language=tmdb_lang)
if show.get('tv_results') and 1 == len(show['tv_results']): if show.get('tv_results') and 1 == len(show['tv_results']):
show = tmdbsimple.TV(id=show['tv_results'][0]['id']).info( show = tmdbsimple.TV(id=show['tv_results'][0]['id']).info(
append_to_response='external_ids') append_to_response='external_ids', language=tmdb_lang)
except (BaseException, Exception): except (BaseException, Exception):
continue continue
self._set_cache_entry(cache_id_key, show, expire=self.search_cache_expire) self._set_cache_entry(cache_id_key, show, expire=self.search_cache_expire)
@ -242,7 +244,7 @@ class TmdbIndexer(TVInfoBase):
is_none, shows = self._get_cache_entry(cache_name_key) is_none, shows = self._get_cache_entry(cache_name_key)
if not self.config.get('cache_search') or (None is shows and not is_none): if not self.config.get('cache_search') or (None is shows and not is_none):
try: try:
shows = tmdbsimple.Search().tv(query=n) shows = tmdbsimple.Search().tv(query=n, language=tmdb_lang)
self._set_cache_entry(cache_name_key, shows, expire=self.search_cache_expire) self._set_cache_entry(cache_name_key, shows, expire=self.search_cache_expire)
results.extend([_make_result_dict(s) for s in shows.get('results') or []]) results.extend([_make_result_dict(s) for s in shows.get('results') or []])
except (BaseException, Exception) as e: except (BaseException, Exception) as e:
@ -253,32 +255,23 @@ class TmdbIndexer(TVInfoBase):
results = [seen.add(r.id) or r for r in results if r.id not in seen] results = [seen.add(r.id) or r for r in results if r.id not in seen]
return results return results
def _convert_person_obj(self, person_obj): def _convert_person_obj(self, tmdb_person_obj):
gender = PersonGenders.tmdb_map.get(person_obj.get('gender'), PersonGenders.unknown) gender = PersonGenders.tmdb_map.get(tmdb_person_obj.get('gender'), PersonGenders.unknown)
try: try:
birthdate = person_obj.get('birthday') and tz_p.parse(person_obj.get('birthday')).date() birthdate = tmdb_person_obj.get('birthday') and tz_p.parse(tmdb_person_obj.get('birthday')).date()
except (BaseException, Exception): except (BaseException, Exception):
birthdate = None birthdate = None
try: try:
deathdate = person_obj.get('deathday') and tz_p.parse(person_obj.get('deathday')).date() deathdate = tmdb_person_obj.get('deathday') and tz_p.parse(tmdb_person_obj.get('deathday')).date()
except (BaseException, Exception): except (BaseException, Exception):
deathdate = None deathdate = None
cast = person_obj.get('cast') or person_obj.get('tv_credits', {}).get('cast') person_imdb_id = tmdb_person_obj.get('imdb_id') and try_int(tmdb_person_obj['imdb_id'].replace('nm', ''), None)
person_ids = {TVINFO_TMDB: tmdb_person_obj.get('id')}
if person_imdb_id:
person_ids.update({TVINFO_IMDB: person_imdb_id})
characters = [] pi = tmdb_person_obj.get('images')
for character in cast or []:
show = TVInfoShow()
show.id = character.get('id')
show.ids = TVInfoIDs(ids={TVINFO_TMDB: show.id})
show.seriesname = clean_data(character.get('original_name'))
show.overview = clean_data(character.get('overview'))
show.firstaired = clean_data(character.get('first_air_date'))
characters.append(
TVInfoCharacter(name=clean_data(character.get('character')), show=show)
)
pi = person_obj.get('images')
image_url, main_image, thumb_url, main_thumb, image_list = None, None, None, None, [] image_url, main_image, thumb_url, main_thumb, image_list = None, None, None, None, []
if pi: if pi:
for i in sorted(pi['profiles'], key=lambda a: a['vote_average'] or 0, reverse=True): for i in sorted(pi['profiles'], key=lambda a: a['vote_average'] or 0, reverse=True):
@ -309,20 +302,62 @@ class TmdbIndexer(TVInfoBase):
rating=i['vote_average'], rating=i['vote_average'],
votes=i['vote_count'] votes=i['vote_count']
)) ))
elif tmdb_person_obj.get('profile_path'):
main_image = '%s%s%s' % (
self.img_base_url, self.size_map[TVInfoImageType.person_poster][TVInfoImageSize.original],
tmdb_person_obj['profile_path'])
main_thumb = '%s%s%s' % (
self.img_base_url, self.size_map[TVInfoImageType.person_poster][TVInfoImageSize.medium],
tmdb_person_obj['profile_path'])
person_imdb_id = person_obj.get('imdb_id') and try_int(person_obj['imdb_id'].replace('nm', ''), None) _it_person_obj = TVInfoPerson(
person_ids = {TVINFO_TMDB: person_obj.get('id')} p_id=tmdb_person_obj.get('id'), ids=TVInfoIDs(ids=person_ids), name=clean_data(tmdb_person_obj.get('name')),
if person_imdb_id: akas=clean_data(set(tmdb_person_obj.get('also_known_as') or [])),
person_ids.update({TVINFO_IMDB: person_imdb_id}) bio=clean_data(tmdb_person_obj.get('biography')), gender=gender,
return TVInfoPerson(
p_id=person_obj.get('id'), ids=person_ids, characters=characters,
name=clean_data(person_obj.get('name')), akas=clean_data(set(person_obj.get('also_known_as') or [])),
bio=clean_data(person_obj.get('biography')), gender=gender,
image=main_image, images=image_list, thumb_url=main_thumb, image=main_image, images=image_list, thumb_url=main_thumb,
birthdate=birthdate, birthplace=clean_data(person_obj.get('place_of_birth')), birthdate=birthdate, birthplace=clean_data(tmdb_person_obj.get('place_of_birth')),
deathdate=deathdate, homepage=person_obj.get('homepage') deathdate=deathdate, homepage=tmdb_person_obj.get('homepage')
) )
cast = tmdb_person_obj.get('cast') or tmdb_person_obj.get('tv_credits', {}).get('cast') or \
tmdb_person_obj.get('known_for')
characters = []
for character in cast or []:
ti_show = TVInfoShow()
ti_show.id = character.get('id')
ti_show.ids = TVInfoIDs(ids={TVINFO_TMDB: ti_show.id})
ti_show.seriesname = enforce_type(clean_data(character.get('original_name')), str, '')
ti_show.overview = self._enforce_text(character.get('overview'))
ti_show.firstaired = clean_data(character.get('first_air_date'))
ti_show.language = clean_data(character.get('original_language'))
ti_show.genre_list = []
for g in character.get('genre_ids') or []:
if g in self.tv_genres:
ti_show.genre_list.append(self.tv_genres.get(g))
ti_show.genre = '|'.join(ti_show.genre_list)
if character.get('poster_path'):
ti_show.poster = '%s%s%s' % \
(self.img_base_url,
self.size_map[TVInfoImageType.person_poster][TVInfoImageSize.original],
character['poster_path'])
ti_show.poster_thumb = '%s%s%s' % \
(self.img_base_url,
self.size_map[TVInfoImageType.person_poster][TVInfoImageSize.medium],
character['poster_path'])
if character.get('backdrop_path'):
ti_show.fanart = '%s%s%s' % \
(self.img_base_url,
self.size_map[TVInfoImageType.person_poster][TVInfoImageSize.original],
character['backdrop_path'])
characters.append(
TVInfoCharacter(name=clean_data(character.get('character')), ti_show=ti_show, person=[_it_person_obj],
episode_count=character.get('episode_count'))
)
_it_person_obj.characters = characters
return _it_person_obj
def _search_person(self, name=None, ids=None): def _search_person(self, name=None, ids=None):
# type: (AnyStr, Dict[integer_types, integer_types]) -> List[TVInfoPerson] # type: (AnyStr, Dict[integer_types, integer_types]) -> List[TVInfoPerson]
""" """
@ -409,31 +444,33 @@ class TmdbIndexer(TVInfoBase):
def _convert_show(self, show_dict, show_obj=None): def _convert_show(self, show_dict, show_obj=None):
# type: (Dict, TVInfoShow) -> TVInfoShow # type: (Dict, TVInfoShow) -> TVInfoShow
if None is show_obj: if None is show_obj:
tv_s = TVInfoShow() ti_show = TVInfoShow()
else: else:
tv_s = show_obj ti_show = show_obj
if show_dict: if show_dict:
tv_s.seriesname = clean_data(show_dict.get('name') or show_dict.get('original_name') ti_show.seriesname = clean_data(show_dict.get('name') or show_dict.get('original_name')
or show_dict.get('original_title')) or show_dict.get('original_title'))
org_title = clean_data(show_dict.get('original_name') or show_dict.get('original_title')) org_title = clean_data(show_dict.get('original_name') or show_dict.get('original_title'))
if org_title != tv_s.seriesname: if org_title != ti_show.seriesname:
tv_s.aliases = [org_title] ti_show.aliases = [org_title]
tv_s.id = show_dict.get('id') ti_show.id = show_dict.get('id')
tv_s.seriesid = tv_s.id ti_show.seriesid = ti_show.id
tv_s.language = clean_data(show_dict.get('original_language')) ti_show.language = clean_data(show_dict.get('original_language'))
tv_s.overview = clean_data(show_dict.get('overview')) ti_show.spoken_languages = [_l['iso_639_1'] for _l in show_dict.get('spoken_languages') or []]
tv_s.status = clean_data(show_dict.get('status', '')) ti_show.overview = self._enforce_text(show_dict.get('overview'))
tv_s.show_type = clean_data((show_dict.get('type') and [show_dict['type']]) or []) ti_show.status = clean_data(show_dict.get('status', ''))
tv_s.firstaired = clean_data(show_dict.get('first_air_date')) ti_show.show_type = clean_data((show_dict.get('type') and [show_dict['type']]) or [])
tv_s.vote_count = show_dict.get('vote_count') ti_show.firstaired = clean_data(show_dict.get('first_air_date'))
tv_s.vote_average = show_dict.get('vote_average') ti_show.popularity = show_dict.get('popularity')
tv_s.popularity = show_dict.get('popularity') ti_show.vote_count = show_dict.get('vote_count')
tv_s.origin_countries = clean_data(show_dict.get('origin_country') or []) ti_show.vote_average = show_dict.get('vote_average')
tv_s.genre_list = [] ti_show.origin_countries = show_dict.get('origin_country') or []
ti_show.genre_list = []
ti_show.origin_countries = clean_data(show_dict.get('origin_country') or [])
for g in show_dict.get('genre_ids') or []: for g in show_dict.get('genre_ids') or []:
if g in self.tv_genres: if g in self.tv_genres:
tv_s.genre_list.append(self.tv_genres.get(g)) ti_show.genre_list.append(self.tv_genres.get(g))
tv_s.genre = '|'.join(tv_s.genre_list) ti_show.genre = '|'.join(ti_show.genre_list)
runtime = None runtime = None
for r in sorted(show_dict.get('episode_run_time') or [], reverse=True): for r in sorted(show_dict.get('episode_run_time') or [], reverse=True):
if 40 < r < 50: if 40 < r < 50:
@ -444,18 +481,18 @@ class TmdbIndexer(TVInfoBase):
break break
if not runtime and show_dict.get('episode_run_time'): if not runtime and show_dict.get('episode_run_time'):
runtime = max(show_dict.get('episode_run_time') or [0]) or None runtime = max(show_dict.get('episode_run_time') or [0]) or None
tv_s.runtime = runtime ti_show.runtime = runtime
tv_s.networks = [ ti_show.networks = [
TVInfoNetwork(name=clean_data(n.get('name')), n_id=n.get('id'), TVInfoNetwork(name=clean_data(n.get('name')), n_id=n.get('id'),
country_code=clean_data(n.get('origin_country'))) country_code=clean_data(n.get('origin_country')))
for n in reversed(show_dict.get('networks') or []) for n in reversed(show_dict.get('networks') or [])
] ]
if show_dict.get('networks'): if show_dict.get('networks'):
tv_s.network = clean_data(show_dict['networks'][-1]['name']) ti_show.network = clean_data(show_dict['networks'][-1]['name'])
tv_s.network_id = show_dict['networks'][-1].get('id') ti_show.network_id = show_dict['networks'][-1].get('id')
tv_s.network_country_code = clean_data(show_dict['networks'][-1].get('origin_country')) ti_show.network_country_code = clean_data(show_dict['networks'][-1].get('origin_country'))
image_url = show_dict.get('poster_path') and '%s%s%s' % \ image_url = show_dict.get('poster_path') and '%s%s%s' % \
(self.img_base_url, self.size_map[TVInfoImageType.poster][TVInfoImageSize.original], (self.img_base_url, self.size_map[TVInfoImageType.poster][TVInfoImageSize.original],
@ -466,19 +503,20 @@ class TmdbIndexer(TVInfoBase):
backdrop_url = show_dict.get('backdrop_path') and '%s%s%s' % \ backdrop_url = show_dict.get('backdrop_path') and '%s%s%s' % \
(self.img_base_url, self.size_map[TVInfoImageType.fanart][TVInfoImageSize.original], (self.img_base_url, self.size_map[TVInfoImageType.fanart][TVInfoImageSize.original],
show_dict.get('backdrop_path')) show_dict.get('backdrop_path'))
tv_s.ids = TVInfoIDs(tvdb=show_dict.get('external_ids', {}).get('tvdb_id'), ti_show.ids = TVInfoIDs(tvdb=show_dict.get('external_ids', {}).get('tvdb_id'),
tmdb=show_dict['id'], tmdb=show_dict['id'],
rage=show_dict.get('external_ids', {}).get('tvrage_id'), rage=show_dict.get('external_ids', {}).get('tvrage_id'),
imdb=show_dict.get('external_ids', {}).get('imdb_id') and imdb=show_dict.get('external_ids', {}).get('imdb_id')
try_int(show_dict.get('external_ids', {}).get('imdb_id', '').replace('tt', ''), None)) and try_int(
tv_s.social_ids = TVInfoSocialIDs(twitter=show_dict.get('external_ids', {}).get('twitter_id'), show_dict.get('external_ids', {}).get('imdb_id', '').replace('tt', ''), None))
ti_show.social_ids = TVInfoSocialIDs(twitter=show_dict.get('external_ids', {}).get('twitter_id'),
instagram=show_dict.get('external_ids', {}).get('instagram_id'), instagram=show_dict.get('external_ids', {}).get('instagram_id'),
facebook=show_dict.get('external_ids', {}).get('facebook_id')) facebook=show_dict.get('external_ids', {}).get('facebook_id'))
tv_s.poster = image_url ti_show.poster = image_url
tv_s.poster_thumb = thumb_image_url ti_show.poster_thumb = thumb_image_url
tv_s.fanart = backdrop_url ti_show.fanart = backdrop_url
return tv_s return ti_show
def _get_show_list(self, src_method, result_count, **kwargs): def _get_show_list(self, src_method, result_count, **kwargs):
result = [] result = []
@ -498,7 +536,26 @@ class TmdbIndexer(TVInfoBase):
pass pass
return result[:result_count] return result[:result_count]
def get_similar(self, tvid, result_count=100, **kwargs):
# type: (integer_types, int, Any) -> List[TVInfoShow]
"""
list of similar shows to the provided tv id
:param tvid: id to find similar shows for
:param result_count: result count to returned
"""
return self._get_show_list(tmdbsimple.TV(id=tvid).similar, result_count)
def get_recommended_for_show(self, tvid, result_count=100, **kwargs):
# type: (integer_types, int, Any) -> List[TVInfoShow]
"""
list of recommended shows to the provided tv id
:param tvid: id to find recommended shows for
:param result_count: result count to returned
"""
return self._get_show_list(tmdbsimple.TV(id=tvid).recommendations, result_count)
def get_trending(self, result_count=100, time_window='day', **kwargs): def get_trending(self, result_count=100, time_window='day', **kwargs):
# type: (int, str, Any) -> List[TVInfoShow]
""" """
list of trending tv shows for day or week list of trending tv shows for day or week
:param result_count: :param result_count:
@ -508,12 +565,15 @@ class TmdbIndexer(TVInfoBase):
return self._get_show_list(tmdbsimple.Trending(media_type='tv', time_window=t_windows).info, result_count) return self._get_show_list(tmdbsimple.Trending(media_type='tv', time_window=t_windows).info, result_count)
def get_popular(self, result_count=100, **kwargs): def get_popular(self, result_count=100, **kwargs):
# type: (int, Any) -> List[TVInfoShow]
return self._get_show_list(tmdbsimple.TV().popular, result_count) return self._get_show_list(tmdbsimple.TV().popular, result_count)
def get_top_rated(self, result_count=100, **kwargs): def get_top_rated(self, result_count=100, **kwargs):
# type: (int, Any) -> List[TVInfoShow]
return self._get_show_list(tmdbsimple.TV().top_rated, result_count) return self._get_show_list(tmdbsimple.TV().top_rated, result_count)
def discover(self, result_count=100, **kwargs): def discover(self, result_count=100, **kwargs):
# type: (int, Any) -> List[TVInfoShow]
""" """
Discover TV shows by different types of data like average rating, Discover TV shows by different types of data like average rating,
number of votes, genres, the network they aired on and air dates. number of votes, genres, the network they aired on and air dates.
@ -596,6 +656,12 @@ class TmdbIndexer(TVInfoBase):
:param result_count: :param result_count:
""" """
if not kwargs:
# use default if now kwargs are set = return all future airdate shows with language set to 'en'
kwargs.update({'sort_by': 'first_air_date.asc',
'first_air_date.gte': datetime.date.today().strftime('%Y-%m-%d'),
'with_original_language': 'en',
})
return self._get_show_list(tmdbsimple.Discover().tv, result_count, **kwargs) return self._get_show_list(tmdbsimple.Discover().tv, result_count, **kwargs)
def _get_show_data(self, sid, language, get_ep_info=False, banners=False, posters=False, seasons=False, def _get_show_data(self, sid, language, get_ep_info=False, banners=False, posters=False, seasons=False,
@ -607,9 +673,9 @@ class TmdbIndexer(TVInfoBase):
tmdb_lang = ('en-US', language)[language in self._tmdb_supported_lang_list] tmdb_lang = ('en-US', language)[language in self._tmdb_supported_lang_list]
if any((banners, posters, seasons, seasonwides, fanart)): if any((banners, posters, seasons, seasonwides, fanart)):
to_append.append('images') to_append.append('images')
if (actors or self.config['actors_enabled']) and not getattr(self.shows.get(sid), 'actors_loaded', False): if (actors or self.config['actors_enabled']) and not getattr(self.ti_shows.get(sid), 'actors_loaded', False):
to_append.append('aggregate_credits') to_append.append('aggregate_credits')
if get_ep_info and not getattr(self.shows.get(sid), 'ep_loaded', False): if get_ep_info and not getattr(self.ti_shows.get(sid), 'ep_loaded', False):
to_append.append('episode_groups') to_append.append('episode_groups')
try: try:
tmdb = tmdbsimple.TV(sid) tmdb = tmdbsimple.TV(sid)
@ -625,7 +691,7 @@ class TmdbIndexer(TVInfoBase):
self.show_not_found = True self.show_not_found = True
return False return False
show_obj = self.shows[sid] show_obj = self.ti_shows[sid]
self._convert_show(show_data, show_obj) self._convert_show(show_data, show_obj)
@ -657,7 +723,7 @@ class TmdbIndexer(TVInfoBase):
) )
season_cast_objs = {} season_cast_objs = {}
if (actors or self.config['actors_enabled']) and not getattr(self.shows.get(sid), 'actors_loaded', False): if (actors or self.config['actors_enabled']) and not getattr(self.ti_shows.get(sid), 'actors_loaded', False):
cast, show_obj.actors_loaded = CastList(), True cast, show_obj.actors_loaded = CastList(), True
if isinstance(show_data.get('aggregate_credits'), dict) and 'cast' in show_data['aggregate_credits'] and\ if isinstance(show_data.get('aggregate_credits'), dict) and 'cast' in show_data['aggregate_credits'] and\
isinstance(show_data['aggregate_credits']['cast'], list): isinstance(show_data['aggregate_credits']['cast'], list):
@ -693,6 +759,7 @@ class TmdbIndexer(TVInfoBase):
person=[ person=[
TVInfoPerson( TVInfoPerson(
p_id=person_obj['id'], name=clean_data(person_obj['name']), p_id=person_obj['id'], name=clean_data(person_obj['name']),
ids=TVInfoIDs(ids={TVINFO_TMDB: person_obj['id']}),
image='%s%s%s' % ( image='%s%s%s' % (
self.img_base_url, self.img_base_url,
self.size_map[TVInfoImageType.person_poster][ self.size_map[TVInfoImageType.person_poster][
@ -724,7 +791,7 @@ class TmdbIndexer(TVInfoBase):
}, },
} for ch in cast[RoleTypes.ActorMain]] } for ch in cast[RoleTypes.ActorMain]]
if get_ep_info and not getattr(self.shows.get(sid), 'ep_loaded', False): if get_ep_info and not getattr(self.ti_shows.get(sid), 'ep_loaded', False):
show_obj.ep_loaded = True show_obj.ep_loaded = True
seasons = ['season/%d' % s['season_number'] for s in show_data.get('seasons') or []] seasons = ['season/%d' % s['season_number'] for s in show_data.get('seasons') or []]
# call limited to 20 seasons per call # call limited to 20 seasons per call
@ -779,3 +846,19 @@ class TmdbIndexer(TVInfoBase):
else: else:
TmdbIndexer._supported_languages = [] TmdbIndexer._supported_languages = []
TmdbIndexer._tmdb_lang_list = [] TmdbIndexer._tmdb_lang_list = []
@staticmethod
def _enforce_text(text):
"""
Set nonsense text to an enforced type
:param text:
:type text: AnyStr
:return:
:rtype: AnyStr
"""
text = enforce_type(clean_data(text), str, '').strip()
tmp = text.lower()
if 'details here' == tmp \
or re.search(r'no(\s\w+){1,2}\savailable', tmp):
return ''
return text

View file

@ -1,14 +1,15 @@
import datetime
import logging import logging
import re import re
from .exceptions import TraktException from .exceptions import TraktException, TraktAuthException
from exceptions_helper import ConnectionSkipException, ex from exceptions_helper import ConnectionSkipException, ex
from six import iteritems from six import iteritems
from .trakt import TraktAPI from .trakt import TraktAPI
from lib.tvinfo_base.exceptions import BaseTVinfoShownotfound from lib.tvinfo_base.exceptions import BaseTVinfoShownotfound
from lib.tvinfo_base import TVInfoBase, TVINFO_TRAKT, TVINFO_TMDB, TVINFO_TVDB, TVINFO_TVRAGE, TVINFO_IMDB, \ from lib.tvinfo_base import TVInfoBase, TVINFO_TRAKT, TVINFO_TMDB, TVINFO_TVDB, TVINFO_TVRAGE, TVINFO_IMDB, \
TVINFO_SLUG, TVInfoPerson, TVINFO_TWITTER, TVINFO_FACEBOOK, TVINFO_WIKIPEDIA, TVINFO_INSTAGRAM, TVInfoCharacter, TVInfoShow, \ TVINFO_SLUG, TVInfoPerson, TVINFO_TWITTER, TVINFO_FACEBOOK, TVINFO_WIKIPEDIA, TVINFO_INSTAGRAM, TVInfoCharacter, \
TVInfoIDs, TVINFO_TRAKT_SLUG TVInfoShow, TVInfoIDs, TVInfoSocialIDs, TVINFO_TRAKT_SLUG, TVInfoEpisode, TVInfoSeason, RoleTypes
from sg_helpers import try_int from sg_helpers import clean_data, enforce_type, try_int
from lib.dateutil.parser import parser from lib.dateutil.parser import parser
# noinspection PyUnreachableCode # noinspection PyUnreachableCode
@ -33,6 +34,7 @@ log.addHandler(logging.NullHandler())
def _convert_imdb_id(src, s_id): def _convert_imdb_id(src, s_id):
# type: (int, integer_types) -> integer_types
if TVINFO_IMDB == src: if TVINFO_IMDB == src:
try: try:
return try_int(re.search(r'(\d+)', s_id).group(1), s_id) return try_int(re.search(r'(\d+)', s_id).group(1), s_id)
@ -100,16 +102,29 @@ class TraktIndexer(TVInfoBase):
@staticmethod @staticmethod
def _make_result_obj(shows, results): def _make_result_obj(shows, results):
# type: (List[Dict], List[TVInfoShow]) -> None
if shows: if shows:
try: try:
for s in shows: for s in shows:
if s['ids']['trakt'] not in [i['ids'].trakt for i in results]: if s['ids']['trakt'] not in [i['ids'].trakt for i in results]:
s['id'] = s['ids']['trakt'] ti_show = TVInfoShow()
s['ids'] = TVInfoIDs( countries = clean_data(s['country'])
trakt=s['ids']['trakt'], tvdb=s['ids']['tvdb'], tmdb=s['ids']['tmdb'], if countries:
countries = [countries]
else:
countries = []
ti_show.id, ti_show.seriesname, ti_show.overview, ti_show.firstaired, ti_show.airs_dayofweek, \
ti_show.runtime, ti_show.network, ti_show.origin_countries, ti_show.official_site, \
ti_show.status, ti_show.rating, ti_show.genre_list, ti_show.ids = s['ids']['trakt'], \
clean_data(s['title']), enforce_type(clean_data(s['overview']), str, ''), s['firstaired'], \
(isinstance(s['airs'], dict) and s['airs']['day']) or '', \
s['runtime'], s['network'], countries, s['homepage'], s['status'], s['rating'], \
s['genres_list'], \
TVInfoIDs(trakt=s['ids']['trakt'], tvdb=s['ids']['tvdb'], tmdb=s['ids']['tmdb'],
rage=s['ids']['tvrage'], rage=s['ids']['tvrage'],
imdb=s['ids']['imdb'] and try_int(s['ids']['imdb'].replace('tt', ''), None)) imdb=s['ids']['imdb'] and try_int(s['ids']['imdb'].replace('tt', ''), None))
results.append(s) ti_show.genre = '|'.join(ti_show.genre_list or [])
results.append(ti_show)
except (BaseException, Exception) as e: except (BaseException, Exception) as e:
log.debug('Error creating result dict: %s' % ex(e)) log.debug('Error creating result dict: %s' % ex(e))
@ -119,7 +134,7 @@ class TraktIndexer(TVInfoBase):
If a custom_ui UI is configured, it uses this to select the correct If a custom_ui UI is configured, it uses this to select the correct
series. series.
""" """
results = [] results = [] # type: List[TVInfoShow]
if ids: if ids:
for t, p in iteritems(ids): for t, p in iteritems(ids):
if t in self.supported_id_searches: if t in self.supported_id_searches:
@ -168,13 +183,13 @@ class TraktIndexer(TVInfoBase):
else: else:
self._make_result_obj(all_series, results) self._make_result_obj(all_series, results)
final_result = [] final_result = [] # type: List[TVInfoShow]
seen = set() seen = set()
film_type = re.compile(r'(?i)films?\)$') film_type = re.compile(r'(?i)films?\)$')
for r in results: for r in results:
if r['id'] not in seen: if r.id not in seen:
seen.add(r['id']) seen.add(r.id)
title = r.get('title') or '' title = r.seriesname or ''
if not film_type.search(title): if not film_type.search(title):
final_result.append(r) final_result.append(r)
else: else:
@ -247,17 +262,19 @@ class TraktIndexer(TVInfoBase):
deathdate=deathdate, deathdate=deathdate,
homepage=person_obj['homepage'], homepage=person_obj['homepage'],
birthplace=person_obj['birthplace'], birthplace=person_obj['birthplace'],
social_ids={TVINFO_TWITTER: person_obj['social_ids']['twitter'], social_ids=TVInfoSocialIDs(
ids={TVINFO_TWITTER: person_obj['social_ids']['twitter'],
TVINFO_FACEBOOK: person_obj['social_ids']['facebook'], TVINFO_FACEBOOK: person_obj['social_ids']['facebook'],
TVINFO_INSTAGRAM: person_obj['social_ids']['instagram'], TVINFO_INSTAGRAM: person_obj['social_ids']['instagram'],
TVINFO_WIKIPEDIA: person_obj['social_ids']['wikipedia'] TVINFO_WIKIPEDIA: person_obj['social_ids']['wikipedia']
}, }),
ids={TVINFO_TRAKT: person_obj['ids']['trakt'], TVINFO_SLUG: person_obj['ids']['slug'], ids=TVInfoIDs(ids={
TVINFO_TRAKT: person_obj['ids']['trakt'], TVINFO_SLUG: person_obj['ids']['slug'],
TVINFO_IMDB: TVINFO_IMDB:
person_obj['ids']['imdb'] and person_obj['ids']['imdb'] and
try_int(person_obj['ids']['imdb'].replace('nm', ''), None), try_int(person_obj['ids']['imdb'].replace('nm', ''), None),
TVINFO_TMDB: person_obj['ids']['tmdb'], TVINFO_TMDB: person_obj['ids']['tmdb'],
TVINFO_TVRAGE: person_obj['ids']['tvrage']}) TVINFO_TVRAGE: person_obj['ids']['tvrage']}))
def get_person(self, p_id, get_show_credits=False, get_images=False, **kwargs): def get_person(self, p_id, get_show_credits=False, get_images=False, **kwargs):
# type: (integer_types, bool, bool, Any) -> Optional[TVInfoPerson] # type: (integer_types, bool, bool, Any) -> Optional[TVInfoPerson]
@ -279,7 +296,7 @@ class TraktIndexer(TVInfoBase):
if not urls: if not urls:
return return
result = None result = None # type: Optional[TVInfoPerson]
for url, show_credits in urls: for url, show_credits in urls:
try: try:
@ -292,25 +309,25 @@ class TraktIndexer(TVInfoBase):
if show_credits: if show_credits:
pc = [] pc = []
for c in resp.get('cast') or []: for c in resp.get('cast') or []:
show = TVInfoShow() ti_show = TVInfoShow()
show.id = c['show']['ids'].get('trakt') ti_show.id = c['show']['ids'].get('trakt')
show.seriesname = c['show']['title'] ti_show.seriesname = c['show']['title']
show.ids = TVInfoIDs(ids={id_map[src]: _convert_imdb_id(id_map[src], sid) ti_show.ids = TVInfoIDs(ids={id_map[src]: _convert_imdb_id(id_map[src], sid)
for src, sid in iteritems(c['show']['ids']) if src in id_map}) for src, sid in iteritems(c['show']['ids']) if src in id_map})
show.network = c['show']['network'] ti_show.network = c['show']['network']
show.firstaired = c['show']['first_aired'] ti_show.firstaired = c['show']['first_aired']
show.overview = c['show']['overview'] ti_show.overview = enforce_type(clean_data(c['show']['overview']), str, '')
show.status = c['show']['status'] ti_show.status = c['show']['status']
show.imdb_id = c['show']['ids'].get('imdb') ti_show.imdb_id = c['show']['ids'].get('imdb')
show.runtime = c['show']['runtime'] ti_show.runtime = c['show']['runtime']
show.genre_list = c['show']['genres'] ti_show.genre_list = c['show']['genres']
for ch in c.get('characters') or []: for ch in c.get('characters') or []:
pc.append( _ti_character = TVInfoCharacter(name=ch, regular=c.get('series_regular'),
TVInfoCharacter( ti_show=ti_show, person=[result],
name=ch, regular=c.get('series_regular'), episode_count=c.get('episode_count'))
show=show pc.append(_ti_character)
) ti_show.cast[(RoleTypes.ActorGuest, RoleTypes.ActorMain)[
) c.get('series_regular', False)]].append(_ti_character)
result.characters = pc result.characters = pc
else: else:
result = self._convert_person_obj(resp) result = self._convert_person_obj(resp)
@ -356,3 +373,268 @@ class TraktIndexer(TVInfoBase):
log.debug('Could not connect to Trakt service: %s' % ex(e)) log.debug('Could not connect to Trakt service: %s' % ex(e))
return result return result
@staticmethod
def _convert_episode(episode_data, show_obj, season_obj):
# type: (Dict, TVInfoShow, TVInfoSeason) -> TVInfoEpisode
ti_episode = TVInfoEpisode(show=show_obj)
ti_episode.season = season_obj
ti_episode.id, ti_episode.episodename, ti_episode.seasonnumber, ti_episode.episodenumber, \
ti_episode.absolute_number, ti_episode.overview, ti_episode.firstaired, ti_episode.runtime, \
ti_episode.rating, ti_episode.vote_count = episode_data.get('ids', {}).get('trakt'), \
clean_data(episode_data.get('title')), episode_data.get('season'), episode_data.get('number'), \
episode_data.get('number_abs'), enforce_type(clean_data(episode_data.get('overview')), str, ''), \
re.sub('T.+$', '', episode_data.get('first_aired') or ''), \
episode_data['runtime'], episode_data.get('rating'), episode_data.get('votes')
if episode_data.get('available_translations'):
ti_episode.language = clean_data(episode_data['available_translations'][0])
ti_episode.ids = TVInfoIDs(ids={id_map[src]: _convert_imdb_id(id_map[src], sid)
for src, sid in iteritems(episode_data['ids']) if src in id_map})
return ti_episode
@staticmethod
def _convert_show(show_data):
# type: (Dict) -> TVInfoShow
_s_d = (show_data, show_data.get('show'))['show' in show_data]
ti_show = TVInfoShow()
ti_show.seriesname, ti_show.id, ti_show.firstaired, ti_show.overview, ti_show.runtime, ti_show.network, \
ti_show.network_country, ti_show.status, ti_show.genre_list, ti_show.language, ti_show.watcher_count, \
ti_show.play_count, ti_show.collected_count, ti_show.collector_count, ti_show.vote_count, \
ti_show.vote_average, ti_show.rating, ti_show.contentrating, ti_show.official_site, ti_show.slug = \
clean_data(_s_d['title']), _s_d['ids']['trakt'], \
re.sub('T.+$', '', _s_d.get('first_aired') or '') or _s_d.get('year'), \
enforce_type(clean_data(_s_d.get('overview')), str, ''), _s_d.get('runtime'), _s_d.get('network'), \
_s_d.get('country'), _s_d.get('status'), _s_d.get('genres', []), _s_d.get('language'), \
show_data.get('watcher_count'), show_data.get('play_count'), show_data.get('collected_count'), \
show_data.get('collector_count'), _s_d.get('votes'), _s_d.get('rating'), _s_d.get('rating'), \
_s_d.get('certification'), _s_d.get('homepage'), _s_d['ids']['slug']
ti_show.ids = TVInfoIDs(ids={id_map[src]: _convert_imdb_id(id_map[src], sid)
for src, sid in iteritems(_s_d['ids']) if src in id_map})
ti_show.genre = '|'.join(ti_show.genre_list or [])
if _s_d.get('trailer'):
ti_show.trailers = {'any': _s_d['trailer']}
if 'episode' in show_data:
ep_data = show_data['episode']
ti_show.next_season_airdate = re.sub('T.+$', '', ep_data.get('first_aired') or '')
ti_season = TVInfoSeason(show=ti_show)
ti_season.number = ep_data['season']
ti_season[ep_data['number']] = TraktIndexer._convert_episode(ep_data, ti_show, ti_season)
ti_show[ep_data['season']] = ti_season
return ti_show
def _get_show_lists(self, url, account=None):
# type: (str, Any) -> List[TVInfoShow]
result = []
if account:
from sickgear import TRAKT_ACCOUNTS
if account in TRAKT_ACCOUNTS and TRAKT_ACCOUNTS[account].active:
kw = {'send_oauth': account}
else:
raise TraktAuthException('Account missing or disabled')
else:
kw = {}
resp = TraktAPI().trakt_request(url, **kw)
if resp:
for _show in resp:
result.append(self._convert_show(_show))
return result
def get_most_played(self, result_count=100, period='weekly', **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get most played shows
:param period: possible values: 'daily', 'weekly', 'monthly', 'yearly', 'all'
:param result_count: how many results are suppose to be returned
"""
use_period = ('weekly', period)[period in ('daily', 'weekly', 'monthly', 'yearly', 'all')]
return self._get_show_lists('shows/played/%s?extended=full&page=%d&limit=%d' % (use_period, 1, result_count))
def get_most_watched(self, result_count=100, period='weekly', **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get most watched shows
:param period: possible values: 'daily', 'weekly', 'monthly', 'yearly', 'all'
:param result_count: how many results are suppose to be returned
"""
use_period = ('weekly', period)[period in ('daily', 'weekly', 'monthly', 'yearly', 'all')]
return self._get_show_lists('shows/watched/%s?extended=full&page=%d&limit=%d' % (use_period, 1, result_count))
def get_most_collected(self, result_count=100, period='weekly', **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get most collected shows
:param period: possible values: 'daily', 'weekly', 'monthly', 'yearly', 'all'
:param result_count: how many results are suppose to be returned
"""
use_period = ('weekly', period)[period in ('daily', 'weekly', 'monthly', 'yearly', 'all')]
return self._get_show_lists('shows/collected/%s?extended=full&page=%d&limit=%d' % (use_period, 1, result_count))
def get_recommended(self, result_count=100, period='weekly', **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get most recommended shows
:param period: possible values: 'daily', 'weekly', 'monthly', 'yearly', 'all'
:param result_count: how many results are suppose to be returned
"""
use_period = ('weekly', period)[period in ('daily', 'weekly', 'monthly', 'yearly', 'all')]
return self._get_show_lists('shows/recommended/%s?extended=full&page=%d&limit=%d' % (use_period, 1, result_count))
def get_recommended_for_account(self, account, result_count=100, ignore_collected=False, ignore_watchlisted=False,
**kwargs):
# type: (...) -> List[TVInfoShow]
"""
get most recommended shows for account
:param account: account to get recommendations for
:param result_count: how many results are suppose to be returned
:param ignore_collected: exclude colleded shows
:param ignore_watchlisted: exclude watchlisted shows
"""
from sickgear import TRAKT_ACCOUNTS
if not account or account not in TRAKT_ACCOUNTS or not TRAKT_ACCOUNTS[account].active:
raise TraktAuthException('Account missing or disabled')
extra_param = []
if ignore_collected:
extra_param.append('ignore_collected=true')
if ignore_watchlisted:
extra_param.append('ignore_watchlisted=true')
return self._get_show_lists('recommendations/shows?extended=full&page=%d&limit=%d%s' %
(1, result_count, ('', '&%s' % '&'.join(extra_param))[0 < len(extra_param)]),
account=account)
def hide_recommended_for_account(self, account, show_ids, **kwargs):
# type: (integer_types, List[integer_types], Any) -> List[integer_types]
"""
hide recommended show for account
:param account: account to get recommendations for
:param show_ids: list of show_ids to no longer recommend for account
:return: list of added ids
"""
from sickgear import TRAKT_ACCOUNTS
if not account or account not in TRAKT_ACCOUNTS or not TRAKT_ACCOUNTS[account].active:
raise TraktAuthException('Account missing or disabled')
if not isinstance(show_ids, list) or not show_ids or any(not isinstance(_i, int) for _i in show_ids):
raise TraktException('list of show_ids (trakt id) required')
resp = TraktAPI().trakt_request('users/hidden/recommendations', send_oauth=account,
data={'shows': [{'ids': {'trakt': _i}} for _i in show_ids]})
if resp and isinstance(resp, dict) and 'added' in resp and 'shows' in resp['added']:
if len(show_ids) == resp['added']['shows']:
return show_ids
if 'not_found' in resp and 'shows' in resp['not_found']:
not_found = [_i['ids']['trakt'] for _i in resp['not_found']['shows']]
else:
not_found = []
return [_i for _i in show_ids if _i not in not_found]
return []
def unhide_recommended_for_account(self, account, show_ids, **kwargs):
# type: (integer_types, List[integer_types], Any) -> List[integer_types]
"""
unhide recommended show for account
:param account: account to get recommendations for
:param show_ids: list of show_ids to be included in possible recommend for account
:return: list of removed ids
"""
from sickgear import TRAKT_ACCOUNTS
if not account or account not in TRAKT_ACCOUNTS or not TRAKT_ACCOUNTS[account].active:
raise TraktAuthException('Account missing or disabled')
if not isinstance(show_ids, list) or not show_ids or any(not isinstance(_i, int) for _i in show_ids):
raise TraktException('list of show_ids (trakt id) required')
resp = TraktAPI().trakt_request('users/hidden/recommendations/remove', send_oauth=account,
data={'shows': [{'ids': {'trakt': _i}} for _i in show_ids]})
if resp and isinstance(resp, dict) and 'deleted' in resp and 'shows' in resp['deleted']:
if len(show_ids) == resp['deleted']['shows']:
return show_ids
if 'not_found' in resp and 'shows' in resp['not_found']:
not_found = [_i['ids']['trakt'] for _i in resp['not_found']['shows']]
else:
not_found = []
return [_i for _i in show_ids if _i not in not_found]
return []
def list_hidden_recommended_for_account(self, account, **kwargs):
# type: (integer_types, Any) -> List[TVInfoShow]
"""
list hidden recommended show for account
:param account: account to get recommendations for
:return: list of hidden shows
"""
from sickgear import TRAKT_ACCOUNTS
if not account or account not in TRAKT_ACCOUNTS or not TRAKT_ACCOUNTS[account].active:
raise TraktAuthException('Account missing or disabled')
return self._get_show_lists('users/hidden/recommendations?type=show', account=account)
def get_watchlisted_for_account(self, account, result_count=100, sort='rank', **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get watchlisted shows for the account
:param account: account to get recommendations for
:param result_count: how many results are suppose to be returned
:param sort: possible values: 'rank', 'added', 'released', 'title'
"""
from sickgear import TRAKT_ACCOUNTS
if not account or account not in TRAKT_ACCOUNTS or not TRAKT_ACCOUNTS[account].active:
raise TraktAuthException('Account missing or disabled')
sort = ('rank', sort)[sort in ('rank', 'added', 'released', 'title')]
return self._get_show_lists('users/%s/watchlist/shows/%s?extended=full&page=%d&limit=%d' %
(TRAKT_ACCOUNTS[account].slug, sort, 1, result_count), account=account)
def get_anticipated(self, result_count=100, **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get most anticipated shows
:param result_count: how many results are suppose to be returned
"""
return self._get_show_lists('shows/anticipated?extended=full&page=%d&limit=%d' % (1, result_count))
def get_trending(self, result_count=100, **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get trending shows
:param result_count: how many results are suppose to be returned
"""
return self._get_show_lists('shows/trending?extended=full&page=%d&limit=%d' % (1, result_count))
def get_popular(self, result_count=100, **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get all popular shows
:param result_count: how many results are suppose to be returned
"""
return self._get_show_lists('shows/popular?extended=full&page=%d&limit=%d' % (1, result_count))
def get_similar(self, tvid, result_count=100, **kwargs):
# type: (integer_types, int, Any) -> List[TVInfoShow]
"""
return list of similar shows to given id
:param tvid: id to give similar shows for
:param result_count: count of results requested
"""
if not isinstance(tvid, int):
raise TraktException('tvid/trakt id for show required')
return self._get_show_lists('shows/%d/related?extended=full&page=%d&limit=%d' % (tvid, 1, result_count))
def get_new_shows(self, result_count=100, start_date=None, days=32, **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get new shows
:param result_count: how many results are suppose to be returned
:param start_date: start date for returned data in format: '2014-09-01'
:param days: number of days to return from start date
"""
if None is start_date:
start_date = (datetime.datetime.now() + datetime.timedelta(days=-16)).strftime('%Y-%m-%d')
return self._get_show_lists('calendars/all/shows/new/%s/%s?extended=full&page=%d&limit=%d' %
(start_date, days, 1, result_count))
def get_new_seasons(self, result_count=100, start_date=None, days=32, **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get new seasons
:param result_count: how many results are suppose to be returned
:param start_date: start date for returned data in format: '2014-09-01'
:param days: number of days to return from start date
"""
if None is start_date:
start_date = (datetime.datetime.now() + datetime.timedelta(days=-16)).strftime('%Y-%m-%d')
return self._get_show_lists('calendars/all/shows/premieres/%s/%s?extended=full&page=%d&limit=%d' %
(start_date, days, 1, result_count))

View file

@ -5,7 +5,6 @@
# repository:http://github.com/dbr/tvdb_api # repository:http://github.com/dbr/tvdb_api
# license:un license (http://unlicense.org/) # license:un license (http://unlicense.org/)
from __future__ import absolute_import
from functools import wraps from functools import wraps
__author__ = 'dbr/Ben' __author__ = 'dbr/Ben'
@ -34,7 +33,7 @@ from lib.cachecontrol import CacheControl, caches
from lib.dateutil.parser import parse from lib.dateutil.parser import parse
from lib.exceptions_helper import ConnectionSkipException from lib.exceptions_helper import ConnectionSkipException
from lib.tvinfo_base import CastList, TVInfoCharacter, CrewList, TVInfoPerson, RoleTypes, \ from lib.tvinfo_base import CastList, TVInfoCharacter, CrewList, TVInfoPerson, RoleTypes, \
TVINFO_TVDB, TVINFO_TVDB_SLUG, TVInfoBase, TVInfoIDs TVINFO_TVDB, TVINFO_TVDB_SLUG, TVInfoBase, TVInfoIDs, TVInfoNetwork, TVInfoShow
from .tvdb_exceptions import TvdbError, TvdbShownotfound, TvdbTokenexpired from .tvdb_exceptions import TvdbError, TvdbShownotfound, TvdbTokenexpired
from .tvdb_ui import BaseUI, ConsoleUI from .tvdb_ui import BaseUI, ConsoleUI
@ -45,7 +44,6 @@ from six import integer_types, iteritems, PY2, string_types
if False: if False:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from typing import Any, AnyStr, Dict, List, Optional, Union from typing import Any, AnyStr, Dict, List, Optional, Union
from lib.tvinfo_base import TVInfoShow
THETVDB_V2_API_TOKEN = {'token': None, 'datetime': datetime.datetime.fromordinal(1)} THETVDB_V2_API_TOKEN = {'token': None, 'datetime': datetime.datetime.fromordinal(1)}
@ -53,7 +51,7 @@ log = logging.getLogger('tvdb.api')
log.addHandler(logging.NullHandler()) log.addHandler(logging.NullHandler())
# noinspection PyUnusedLocal # noinspection HttpUrlsUsage,PyUnusedLocal
def _record_hook(r, *args, **kwargs): def _record_hook(r, *args, **kwargs):
r.hook_called = True r.hook_called = True
if 301 == r.status_code and isinstance(r.headers.get('Location'), string_types) \ if 301 == r.status_code and isinstance(r.headers.get('Location'), string_types) \
@ -65,8 +63,8 @@ def _record_hook(r, *args, **kwargs):
def retry(exception_to_check, tries=4, delay=3, backoff=2): def retry(exception_to_check, tries=4, delay=3, backoff=2):
"""Retry calling the decorated function using an exponential backoff. """Retry calling the decorated function using an exponential backoff.
http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/ www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry original from: wiki.python.org/moin/PythonDecoratorLibrary#Retry
:param exception_to_check: the exception to check. may be a tuple of :param exception_to_check: the exception to check. may be a tuple of
exceptions to check exceptions to check
@ -223,7 +221,7 @@ class Tvdb(TVInfoBase):
tvdb_api's own key (fine for small scripts), but you can use your tvdb_api's own key (fine for small scripts), but you can use your
own key if desired - this is recommended if you are embedding own key if desired - this is recommended if you are embedding
tvdb_api in a larger application) tvdb_api in a larger application)
See http://thetvdb.com/?tab=apiregister to get your own key See thetvdb.com/?tab=apiregister to get your own key
""" """
@ -335,13 +333,15 @@ class Tvdb(TVInfoBase):
def _search_show(self, name=None, ids=None, **kwargs): def _search_show(self, name=None, ids=None, **kwargs):
# type: (AnyStr, Dict[integer_types, integer_types], Optional[Any]) -> List[TVInfoShow] # type: (AnyStr, Dict[integer_types, integer_types], Optional[Any]) -> List[TVInfoShow]
def map_data(data): def make_tvinfoshow(data):
if not data.get('poster'): _ti_show = TVInfoShow()
data['poster'] = data.get('image') _ti_show.id, _ti_show.banner, _ti_show.firstaired, _ti_show.poster, _ti_show.network, _ti_show.overview, \
data['ids'] = TVInfoIDs( _ti_show.seriesname, _ti_show.slug, _ti_show.status, _ti_show.aliases, _ti_show.ids = \
tvdb=data.get('id'), clean_data(data['id']), clean_data(data.get('banner')), clean_data(data.get('firstaired')), \
imdb=data.get('imdb_id') and try_int(data.get('imdb_id', '').replace('tt', ''), None)) clean_data(data.get('poster')), clean_data(data.get('network')), clean_data(data.get('overview')), \
return data clean_data(data.get('seriesname')), clean_data(data.get('slug')), clean_data(data.get('status')), \
clean_data((data.get('aliases'))), TVInfoIDs(tvdb=try_int(clean_data(data['id'])))
return _ti_show
results = [] results = []
if ids: if ids:
@ -357,7 +357,7 @@ class Tvdb(TVInfoBase):
else: else:
d_m = shows d_m = shows
if d_m: if d_m:
results = list(map(map_data, [d_m['data']])) results.append(make_tvinfoshow(d_m['data']))
if ids.get(TVINFO_TVDB_SLUG): if ids.get(TVINFO_TVDB_SLUG):
cache_id_key = 's-id-%s-%s' % (TVINFO_TVDB, ids[TVINFO_TVDB_SLUG]) cache_id_key = 's-id-%s-%s' % (TVINFO_TVDB, ids[TVINFO_TVDB_SLUG])
is_none, shows = self._get_cache_entry(cache_id_key) is_none, shows = self._get_cache_entry(cache_id_key)
@ -372,7 +372,7 @@ class Tvdb(TVInfoBase):
if d_m: if d_m:
for r in d_m: for r in d_m:
if ids.get(TVINFO_TVDB_SLUG) == r['slug']: if ids.get(TVINFO_TVDB_SLUG) == r['slug']:
results = list(map(map_data, [r])) results.append(make_tvinfoshow(r))
break break
if name: if name:
for n in ([name], name)[isinstance(name, list)]: for n in ([name], name)[isinstance(name, list)]:
@ -389,7 +389,7 @@ class Tvdb(TVInfoBase):
if r: if r:
if not isinstance(r, list): if not isinstance(r, list):
r = [r] r = [r]
results.extend(list(map(map_data, r))) results.extend([make_tvinfoshow(_s) for _s in r])
seen = set() seen = set()
results = [seen.add(r['id']) or r for r in results if r['id'] not in seen] results = [seen.add(r['id']) or r for r in results if r['id'] not in seen]
@ -948,9 +948,6 @@ class Tvdb(TVInfoBase):
role_image = self._make_image(self.config['url_artworks'], role_image) role_image = self._make_image(self.config['url_artworks'], role_image)
character_name = n.get('role', '').strip() or alts.get(n['id'], {}).get('role', '') character_name = n.get('role', '').strip() or alts.get(n['id'], {}).get('role', '')
person_name = n.get('name', '').strip() or alts.get(n['id'], {}).get('name', '') person_name = n.get('name', '').strip() or alts.get(n['id'], {}).get('name', '')
try:
person_id = try_int(re.search(r'^person/(\d+)/', n.get('image', '')).group(1), None)
except (BaseException, Exception):
person_id = None person_id = None
person_id = person_id or alts.get(n['id'], {}).get('person_id') person_id = person_id or alts.get(n['id'], {}).get('person_id')
character_id = n.get('id', None) or alts.get(n['id'], {}).get('rid') character_id = n.get('id', None) or alts.get(n['id'], {}).get('rid')
@ -972,12 +969,12 @@ class Tvdb(TVInfoBase):
cast[RoleTypes.ActorMain].append( cast[RoleTypes.ActorMain].append(
TVInfoCharacter( TVInfoCharacter(
p_id=character_id, name=character_name, person=[TVInfoPerson(p_id=person_id, name=person_name)], p_id=character_id, name=character_name, person=[TVInfoPerson(p_id=person_id, name=person_name)],
image=role_image, show=self.shows[sid])) image=role_image, show=self.ti_shows[sid]))
except (BaseException, Exception): except (BaseException, Exception):
pass pass
self._set_show_data(sid, 'actors', a) self._set_show_data(sid, 'actors', a)
self._set_show_data(sid, 'cast', cast) self._set_show_data(sid, 'cast', cast)
self.shows[sid].actors_loaded = True self.ti_shows[sid].actors_loaded = True
def get_episode_data(self, epid): def get_episode_data(self, epid):
# Parse episode information # Parse episode information
@ -1005,7 +1002,7 @@ class Tvdb(TVInfoBase):
mapped_img_types = {'banner': 'series'} mapped_img_types = {'banner': 'series'}
excluded_main_data = enabled_type in ['seasons_enabled', 'seasonwides_enabled'] excluded_main_data = enabled_type in ['seasons_enabled', 'seasonwides_enabled']
loaded_name = '%s_loaded' % image_type loaded_name = '%s_loaded' % image_type
if (type_bool or self.config[enabled_type]) and not getattr(self.shows.get(sid), loaded_name, False): if (type_bool or self.config[enabled_type]) and not getattr(self.ti_shows.get(sid), loaded_name, False):
image_data = self._getetsrc(self.config['url_series_images'] % image_data = self._getetsrc(self.config['url_series_images'] %
(sid, mapped_img_types.get(image_type, image_type)), language=language) (sid, mapped_img_types.get(image_type, image_type)), language=language)
if image_data and 0 < len(image_data.get('data', '') or ''): if image_data and 0 < len(image_data.get('data', '') or ''):
@ -1018,12 +1015,12 @@ class Tvdb(TVInfoBase):
self._set_show_data(sid, f'{image_type}_thumb', url_thumb) self._set_show_data(sid, f'{image_type}_thumb', url_thumb)
excluded_main_data = True # artwork found so prevent fallback excluded_main_data = True # artwork found so prevent fallback
self._parse_banners(sid, image_data['data']) self._parse_banners(sid, image_data['data'])
self.shows[sid].__dict__[loaded_name] = True self.ti_shows[sid].__dict__[loaded_name] = True
# fallback image thumbnail for none excluded_main_data if artwork is not found # fallback image thumbnail for none excluded_main_data if artwork is not found
if not excluded_main_data and show_data['data'].get(image_type): if not excluded_main_data and show_data.get(image_type):
self._set_show_data(sid, f'{image_type}_thumb', self._set_show_data(sid, f'{image_type}_thumb',
re.sub(r'\.jpg$', '_t.jpg', show_data['data'][image_type], flags=re.I)) re.sub(r'\.jpg$', '_t.jpg', show_data[image_type], flags=re.I))
def _get_show_data(self, def _get_show_data(self,
sid, # type: integer_types sid, # type: integer_types
@ -1045,7 +1042,8 @@ class Tvdb(TVInfoBase):
# Parse show information # Parse show information
url = self.config['url_series_info'] % sid url = self.config['url_series_info'] % sid
if direct_data or sid not in self.shows or None is self.shows[sid].id or language != self.shows[sid].language: if direct_data or sid not in self.ti_shows or None is self.ti_shows[sid].id or \
language != self.ti_shows[sid].language:
log.debug('Getting all series data for %s' % sid) log.debug('Getting all series data for %s' % sid)
show_data = self._getetsrc(url, language=language) show_data = self._getetsrc(url, language=language)
if not show_data or not show_data.get('data'): if not show_data or not show_data.get('data'):
@ -1057,13 +1055,34 @@ class Tvdb(TVInfoBase):
if not (show_data and 'seriesname' in show_data.get('data', {}) or {}): if not (show_data and 'seriesname' in show_data.get('data', {}) or {}):
return False return False
for k, v in iteritems(show_data['data']): show_data = show_data['data']
self._set_show_data(sid, k, v) ti_show = self.ti_shows[sid] # type: TVInfoShow
self._set_show_data(sid, 'ids', ti_show.banner_loaded = ti_show.poster_loaded = ti_show.fanart_loaded = True
TVInfoIDs( ti_show.id = show_data['id']
tvdb=show_data['data'].get('id'), ti_show.seriesname = clean_data(show_data.get('seriesname'))
imdb=show_data['data'].get('imdb_id') ti_show.slug = clean_data(show_data.get('slug'))
and try_int(show_data['data'].get('imdb_id', '').replace('tt', ''), None))) ti_show.poster = clean_data(show_data.get('poster'))
ti_show.banner = clean_data(show_data.get('banner'))
ti_show.fanart = clean_data(show_data.get('fanart'))
ti_show.firstaired = clean_data(show_data.get('firstAired'))
ti_show.rating = show_data.get('rating')
ti_show.contentrating = clean_data(show_data.get('contentRatings'))
ti_show.aliases = show_data.get('aliases') or []
ti_show.status = clean_data(show_data['status'])
if clean_data(show_data.get('network')):
ti_show.network = clean_data(show_data['network'])
ti_show.networks = [TVInfoNetwork(clean_data(show_data['network']),
n_id=clean_data(show_data.get('networkid')))]
ti_show.runtime = try_int(show_data.get('runtime'), 0)
ti_show.language = clean_data(show_data.get('language'))
ti_show.genre = clean_data(show_data.get('genre'))
ti_show.genre_list = clean_data(show_data.get('genre_list')) or []
ti_show.overview = clean_data(show_data.get('overview'))
ti_show.imdb_id = clean_data(show_data.get('imdb_id')) or None
ti_show.airs_time = clean_data(show_data.get('airs_time'))
ti_show.airs_dayofweek = clean_data(show_data.get('airs_dayofweek'))
ti_show.ids = TVInfoIDs(tvdb=ti_show.id, imdb=try_int(ti_show.imdb_id.replace('tt', ''), None))
else: else:
show_data = {'data': {}} show_data = {'data': {}}
@ -1074,31 +1093,46 @@ class Tvdb(TVInfoBase):
('seasonwide', 'seasonwides_enabled', seasonwides)]: ('seasonwide', 'seasonwides_enabled', seasonwides)]:
self._parse_images(sid, language, show_data, img_type, en_type, p_type) self._parse_images(sid, language, show_data, img_type, en_type, p_type)
if (actors or self.config['actors_enabled']) and not getattr(self.shows.get(sid), 'actors_loaded', False): if (actors or self.config['actors_enabled']) and not getattr(self.ti_shows.get(sid), 'actors_loaded', False):
actor_data = self._getetsrc(self.config['url_actors_info'] % sid, language=language) actor_data = self._getetsrc(self.config['url_actors_info'] % sid, language=language)
actor_data_alt = self._getetsrc(self.config['url_series_people'] % sid, language=language) actor_data_alt = self._getetsrc(self.config['url_series_people'] % sid, language=language)
if actor_data and 0 < len(actor_data.get('data', '') or '') or actor_data_alt and actor_data_alt['data']: if actor_data and 0 < len(actor_data.get('data', '') or '') or actor_data_alt and actor_data_alt['data']:
self._parse_actors(sid, actor_data and actor_data.get('data', ''), actor_data_alt and actor_data_alt['data']) self._parse_actors(sid, actor_data and actor_data.get('data', ''), actor_data_alt and actor_data_alt['data'])
if get_ep_info and not getattr(self.shows.get(sid), 'ep_loaded', False): if get_ep_info and not getattr(self.ti_shows.get(sid), 'ep_loaded', False):
# Parse episode data # Parse episode data
log.debug('Getting all episodes of %s' % sid) log.debug('Getting all episodes of %s' % sid)
page = 1 page = 0 # type: int
episodes = [] episodes = [] # type: list
episode_data_found = False # type: bool
episode_data_broken = False # type: bool
page_count = 0 # type: int
pages_loaded = 0 # type: int
start_page = 0 # type: int
while page <= 400: while page <= 400:
episode_data = {} episode_data = {}
if self.is_apikey(): if self.is_apikey() and not episode_data_broken:
episode_data = self._getetsrc( episode_data = self._getetsrc(
self.config['url_series_episodes_info'] % (sid, page), language=language) self.config['url_series_episodes_info'] % (sid, page), language=language)
# fallback to correct old pagination
if 0 == page and None is episode_data:
page = 1
continue
if episode_data:
if 1 == page and not bool(episodes):
start_page = 1
pages_loaded += 1
episode_data_found |= start_page == page and bool(episode_data)
if not episode_data: if episode_data_broken or \
(not episode_data_found and isinstance(show_data, dict) and 'slug' in show_data):
response = {'data': None} response = {'data': None}
items_found = False items_found = False
# fallback to page 'all' if dvd is enabled and response has no items # fallback to page 'all' if dvd is enabled and response has no items
for page_type in ('url_series_dvd', 'url_series_all'): for page_type in ('url_series_dvd', 'url_series_all'):
if 'dvd' not in page_type or self.config['dvdorder']: if 'dvd' not in page_type or self.config['dvdorder']:
response = self._load_url(self.config[page_type] % show_data.get('data').get('slug')) response = self._load_url(self.config[page_type] % show_data.get('slug'))
with BS4Parser(response.get('data') or '') as soup: with BS4Parser(response.get('data') or '') as soup:
items_found = bool(soup.find_all(class_='list-group-item')) items_found = bool(soup.find_all(class_='list-group-item'))
if items_found: if items_found:
@ -1110,7 +1144,7 @@ class Tvdb(TVInfoBase):
with BS4Parser(response.get('data')) as soup: with BS4Parser(response.get('data')) as soup:
items = soup.find_all(class_='list-group-item') items = soup.find_all(class_='list-group-item')
rc_sxe = re.compile(r'(?i)s(?:pecial\s*)?(\d+)\s*[xe]\s*(\d+)') # Special nxn or SnnEnn rc_sxe = re.compile(r'(?i)s(?:pecial\s*)?(\d+)\s*[xe]\s*(\d+)') # Special nxn or SnnEnn
rc_episode = re.compile(r'(?i)/series/%s/episodes?/(?P<ep_id>\d+)' % show_data['data']['slug']) rc_episode = re.compile(r'(?i)/series/%s/episodes?/(?P<ep_id>\d+)' % show_data['slug'])
rc_date = re.compile(r'\s\d{4}\s*$') rc_date = re.compile(r'\s\d{4}\s*$')
season_type, episode_type = ['%s%s' % (('aired', 'dvd')['dvd' in page_type], x) season_type, episode_type = ['%s%s' % (('aired', 'dvd')['dvd' in page_type], x)
for x in ('season', 'episodenumber')] for x in ('season', 'episodenumber')]
@ -1146,18 +1180,25 @@ class Tvdb(TVInfoBase):
'filename': ep_filename, # 'network': ep_network 'filename': ep_filename, # 'network': ep_network
}) })
if not show_data['data']['firstaired'] and ep_aired \ if not show_data['firstaired'] and ep_aired \
and (1, 1) == (ep_season, ep_episode): and (1, 1) == (ep_season, ep_episode):
show_data['data']['firstaired'] = ep_aired show_data['firstaired'] = ep_aired
episode_data['fallback'] = True episode_data['fallback'] = True
except (BaseException, Exception): except (BaseException, Exception):
continue continue
if None is episode_data: if episode_data_found and not episode_data:
if pages_loaded < page_count or 0 == page_count:
episode_data_broken = True
continue
else:
break
if None is episode_data and not bool(episodes) and not episode_data_found:
raise TvdbError('Exception retrieving episodes for show') raise TvdbError('Exception retrieving episodes for show')
if isinstance(episode_data, dict) and not episode_data.get('data', []): if isinstance(episode_data, dict) and not episode_data.get('data', []):
if 1 != page: if start_page != page:
self.not_found = False self.not_found = False
break break
if not getattr(self, 'not_found', False) and None is not episode_data.get('data'): if not getattr(self, 'not_found', False) and None is not episode_data.get('data'):
@ -1166,11 +1207,16 @@ class Tvdb(TVInfoBase):
# check if page is a valid following page # check if page is a valid following page
if not isinstance(next_link, integer_types) or next_link <= page: if not isinstance(next_link, integer_types) or next_link <= page:
next_link = None next_link = None
if isinstance(episode_data, dict) and 'links' in episode_data \
and isinstance(episode_data['links'], dict) and 'last' in episode_data['links'] \
and isinstance(episode_data['links']['last'], int) \
and episode_data['links']['last'] > page_count:
page_count = episode_data['links']['last']
if not next_link and isinstance(episode_data, dict) \ if not next_link and isinstance(episode_data, dict) \
and isinstance(episode_data.get('data', []), list) and \ and isinstance(episode_data.get('data', []), list) and \
(100 > len(episode_data.get('data', [])) or episode_data.get('fallback')): (100 > len(episode_data.get('data', [])) or episode_data.get('fallback')):
break break
if next_link: if isinstance(next_link, int) and page + 1 == next_link:
page = next_link page = next_link
else: else:
page += 1 page += 1
@ -1201,7 +1247,7 @@ class Tvdb(TVInfoBase):
ep_no = int(float(elem_epno)) ep_no = int(float(elem_epno))
if not cur_ep.get('network'): if not cur_ep.get('network'):
cur_ep['network'] = self.shows[sid].network cur_ep['network'] = self.ti_shows[sid].network
for k, v in iteritems(cur_ep): for k, v in iteritems(cur_ep):
k = k.lower() k = k.lower()
@ -1226,7 +1272,7 @@ class Tvdb(TVInfoBase):
try: try:
for guest in cur_ep.get('gueststars_list', []): for guest in cur_ep.get('gueststars_list', []):
cast[RoleTypes.ActorGuest].append(TVInfoCharacter(person=[TVInfoPerson(name=guest)], cast[RoleTypes.ActorGuest].append(TVInfoCharacter(person=[TVInfoPerson(name=guest)],
show=self.shows[sid])) show=self.ti_shows[sid]))
except (BaseException, Exception): except (BaseException, Exception):
pass pass
try: try:
@ -1237,7 +1283,7 @@ class Tvdb(TVInfoBase):
self._set_item(sid, seas_no, ep_no, 'crew', crew) self._set_item(sid, seas_no, ep_no, 'crew', crew)
self._set_item(sid, seas_no, ep_no, 'cast', cast) self._set_item(sid, seas_no, ep_no, 'cast', cast)
self.shows[sid].ep_loaded = True self.ti_shows[sid].ep_loaded = True
return True return True
@ -1259,6 +1305,11 @@ class Tvdb(TVInfoBase):
self.corrections.update(dict([(x['seriesname'], int(x['id'])) for x in selected_series])) self.corrections.update(dict([(x['seriesname'], int(x['id'])) for x in selected_series]))
return sids return sids
def _get_languages(self):
if not Tvdb._supported_languages:
Tvdb._supported_languages = [{'id': _l, 'name': None, 'nativeName': None, 'sg_lang': _l}
for _l in self.config['valid_languages']]
def main(): def main():
"""Simple example of using tvdb_api - it just """Simple example of using tvdb_api - it just

View file

@ -9,7 +9,6 @@
urllib2 caching handler urllib2 caching handler
Modified from http://code.activestate.com/recipes/491261/ Modified from http://code.activestate.com/recipes/491261/
""" """
from __future__ import with_statement
__author__ = "dbr/Ben" __author__ = "dbr/Ben"
__version__ = "1.9" __version__ = "1.9"

View file

@ -11,7 +11,7 @@ __author__ = 'dbr/Ben'
__version__ = '1.9' __version__ = '1.9'
__all__ = ['TvdbException', 'TvdbError', 'TvdbUserabort', 'TvdbShownotfound', __all__ = ['TvdbException', 'TvdbError', 'TvdbUserabort', 'TvdbShownotfound',
'TvdbSeasonnotfound', 'TvdbEpisodenotfound', 'TvdbAttributenotfound', 'TvdbTokenexpired'] 'TvdbSeasonnotfound', 'TvdbEpisodenotfound', 'TvdbAttributenotfound', 'TvdbTokenexpired', 'TvdbTokenFailure']
from lib.tvinfo_base.exceptions import * from lib.tvinfo_base.exceptions import *
@ -64,3 +64,9 @@ class TvdbTokenexpired(BaseTVinfoAuthenticationerror, TvdbError):
"""token expired or missing thetvdb.com """token expired or missing thetvdb.com
""" """
pass pass
class TvdbTokenFailure(BaseTVinfoAuthenticationerror, TvdbError):
"""getting token failed
"""
pass

View file

@ -16,7 +16,7 @@ from requests.adapters import HTTPAdapter
from tornado._locale_data import LOCALE_NAMES from tornado._locale_data import LOCALE_NAMES
from urllib3.util.retry import Retry from urllib3.util.retry import Retry
from sg_helpers import clean_data, get_url, try_int from sg_helpers import clean_data, enforce_type, get_url, try_int
from lib.dateutil.parser import parser from lib.dateutil.parser import parser
# noinspection PyProtectedMember # noinspection PyProtectedMember
from lib.dateutil.tz.tz import _datetime_to_timestamp from lib.dateutil.tz.tz import _datetime_to_timestamp
@ -103,7 +103,7 @@ show_map = {
# 'siteratingcount': '', # 'siteratingcount': '',
# 'lastupdated': '', # 'lastupdated': '',
# 'contentrating': '', # 'contentrating': '',
'rating': 'rating', # 'rating': 'rating',
'status': 'status', 'status': 'status',
'overview': 'summary', 'overview': 'summary',
# 'poster': 'image', # 'poster': 'image',
@ -152,21 +152,28 @@ class TvMaze(TVInfoBase):
if language in cur_locale[1]['name_en'].lower(): if language in cur_locale[1]['name_en'].lower():
language_country_code = cur_locale[0].split('_')[1].lower() language_country_code = cur_locale[0].split('_')[1].lower()
break break
return {'seriesname': clean_data(s.name), 'id': s.id, 'firstaired': clean_data(s.premiered), ti_show = TVInfoShow()
'network': clean_data((s.network and s.network.name) or (s.web_channel and s.web_channel.name)), show_type = clean_data(s.type)
'genres': clean_data(isinstance(s.genres, list) and '|'.join(g.lower() for g in s.genres) or if show_type:
s.genres), show_type = [show_type]
'overview': clean_data(s.summary), 'language': clean_data(s.language), else:
'language_country_code': clean_data(language_country_code), show_type = []
'runtime': s.average_runtime or s.runtime, ti_show.seriesname, ti_show.id, ti_show.firstaired, ti_show.network, ti_show.genre_list, ti_show.overview, \
'type': clean_data(s.type), 'schedule': s.schedule, 'status': clean_data(s.status), ti_show.language, ti_show.runtime, ti_show.show_type, ti_show.airs_dayofweek, ti_show. status, \
'official_site': clean_data(s.official_site), ti_show.official_site, ti_show.aliases, ti_show.poster, ti_show.ids = clean_data(s.name), s.id, \
'aliases': [clean_data(a.name) for a in s.akas], 'image': s.image and s.image.get('original'), clean_data(s.premiered), \
'poster': s.image and s.image.get('original'), clean_data((s.network and s.network.name) or (s.web_channel and s.web_channel.name)), \
'ids': TVInfoIDs( isinstance(s.genres, list) and [clean_data(g.lower()) for g in s.genres], \
tvdb=s.externals.get('thetvdb'), rage=s.externals.get('tvrage'), tvmaze=s.id, enforce_type(clean_data(s.summary), str, ''), clean_data(s.language), \
imdb=clean_data(s.externals.get('imdb') and try_int(s.externals.get('imdb').replace('tt', ''), s.average_runtime or s.runtime, show_type, ', '.join(s.schedule['days'] or []), clean_data(s.status), \
None)))} clean_data(s.official_site), [clean_data(a.name) for a in s.akas], \
s.image and s.image.get('original'), \
TVInfoIDs(tvdb=s.externals.get('thetvdb'), rage=s.externals.get('tvrage'), tvmaze=s.id,
imdb=clean_data(s.externals.get('imdb') and
try_int(s.externals.get('imdb').replace('tt', ''), None)))
ti_show.genre = '|'.join(ti_show.genre_list or [])
return ti_show
results = [] results = []
if ids: if ids:
for t, p in iteritems(ids): for t, p in iteritems(ids):
@ -230,18 +237,24 @@ class TvMaze(TVInfoBase):
('episodename', 'title'), ('overview', 'summary'), ('firstaired', 'airdate'), ('episodename', 'title'), ('overview', 'summary'), ('firstaired', 'airdate'),
('airtime', 'airtime'), ('runtime', 'runtime'), ('airtime', 'airtime'), ('runtime', 'runtime'),
('seriesid', 'maze_id'), ('id', 'maze_id'), ('is_special', 'special'), ('filename', 'image')): ('seriesid', 'maze_id'), ('id', 'maze_id'), ('is_special', 'special'), ('filename', 'image')):
if 'filename' == _k: if 'airtime' == _k:
try:
airtime = datetime.time.fromisoformat(clean_data(getattr(ep_obj, _s, getattr(empty_ep, _k))))
except (BaseException, Exception):
airtime = None
self._set_item(sid, ep_obj.season_number, ep_obj.episode_number or 0, _k, airtime)
elif 'filename' == _k:
image = getattr(ep_obj, _s, {}) or {} image = getattr(ep_obj, _s, {}) or {}
image = image.get('original') or image.get('medium') image = image.get('original') or image.get('medium')
self._set_item(sid, ep_obj.season_number, ep_obj.episode_number, _k, image) self._set_item(sid, ep_obj.season_number, ep_obj.episode_number or 0, _k, image)
else: else:
self._set_item(sid, ep_obj.season_number, ep_obj.episode_number, _k, self._set_item(sid, ep_obj.season_number, ep_obj.episode_number or 0, _k,
clean_data(getattr(ep_obj, _s, getattr(empty_ep, _k)))) clean_data(getattr(ep_obj, _s, getattr(empty_ep, _k))))
if ep_obj.airstamp: if ep_obj.airstamp:
try: try:
at = _datetime_to_timestamp(tz_p.parse(ep_obj.airstamp)) at = _datetime_to_timestamp(tz_p.parse(ep_obj.airstamp))
self._set_item(sid, ep_obj.season_number, ep_obj.episode_number, 'timestamp', at) self._set_item(sid, ep_obj.season_number, ep_obj.episode_number or 0, 'timestamp', at)
except (BaseException, Exception): except (BaseException, Exception):
pass pass
@ -317,140 +330,15 @@ class TvMaze(TVInfoBase):
if not show_data: if not show_data:
return False return False
ti_show = self.shows[sid] # type: TVInfoShow ti_show = self.ti_shows[sid] # type: TVInfoShow
show_obj = ti_show.__dict__ self._show_info_loader(
for k, v in iteritems(show_obj): sid, show_data, ti_show,
if k not in ('cast', 'crew', 'images', 'aliases'): load_images=banners or posters or fanart or
show_obj[k] = getattr(show_data, show_map.get(k, k), clean_data(show_obj[k])) any(self.config.get('%s_enabled' % t, False) for t in ('banners', 'posters', 'fanart')),
ti_show.aliases = [clean_data(a.name) for a in show_data.akas] load_actors=(actors or self.config['actors_enabled'])
ti_show.runtime = show_data.average_runtime or show_data.runtime
p_set = False
if show_data.image:
p_set = True
ti_show.poster = show_data.image.get('original')
ti_show.poster_thumb = show_data.image.get('medium')
if (banners or posters or fanart or
any(self.config.get('%s_enabled' % t, False) for t in ('banners', 'posters', 'fanart'))) and \
not all(getattr(ti_show, '%s_loaded' % t, False) for t in ('poster', 'banner', 'fanart')):
if show_data.images:
ti_show.poster_loaded = True
ti_show.banner_loaded = True
ti_show.fanart_loaded = True
self._set_images(ti_show, show_data, p_set)
if show_data.schedule:
if 'time' in show_data.schedule:
ti_show.airs_time = show_data.schedule['time']
try:
h, m = show_data.schedule['time'].split(':')
h, m = try_int(h, None), try_int(m, None)
if None is not h and None is not m:
ti_show.time = datetime.time(hour=h, minute=m)
except (BaseException, Exception):
pass
if 'days' in show_data.schedule:
ti_show.airs_dayofweek = ', '.join(show_data.schedule['days'])
if show_data.genres:
ti_show.genre = '|'.join(show_data.genres).lower()
if (actors or self.config['actors_enabled']) and not getattr(self.shows.get(sid), 'actors_loaded', False):
if show_data.cast:
character_person_ids = {}
for cur_ch in ti_show.cast[RoleTypes.ActorMain]:
character_person_ids.setdefault(cur_ch.id, []).extend([p.id for p in cur_ch.person])
for cur_ch in show_data.cast.characters:
existing_character = next((c for c in ti_show.cast[RoleTypes.ActorMain] if c.id == cur_ch.id),
None) # type: Optional[TVInfoCharacter]
person = self._convert_person(cur_ch.person)
if existing_character:
existing_person = next((p for p in existing_character.person
if person.id == p.ids.get(TVINFO_TVMAZE)),
None) # type: TVInfoPerson
if existing_person:
try:
character_person_ids[cur_ch.id].remove(existing_person.id)
except (BaseException, Exception):
print('error')
pass
(existing_person.p_id, existing_person.name, existing_person.image, existing_person.gender,
existing_person.birthdate, existing_person.deathdate, existing_person.country,
existing_person.country_code, existing_person.country_timezone, existing_person.thumb_url,
existing_person.url, existing_person.ids) = \
(cur_ch.person.id, clean_data(cur_ch.person.name),
cur_ch.person.image and cur_ch.person.image.get('original'),
PersonGenders.named.get(
cur_ch.person.gender and cur_ch.person.gender.lower(), PersonGenders.unknown),
person.birthdate, person.deathdate,
cur_ch.person.country and clean_data(cur_ch.person.country.get('name')),
cur_ch.person.country and clean_data(cur_ch.person.country.get('code')),
cur_ch.person.country and clean_data(cur_ch.person.country.get('timezone')),
cur_ch.person.image and cur_ch.person.image.get('medium'),
cur_ch.person.url, {TVINFO_TVMAZE: cur_ch.person.id})
else:
existing_character.person.append(person)
else:
ti_show.cast[RoleTypes.ActorMain].append(
TVInfoCharacter(image=cur_ch.image and cur_ch.image.get('original'), name=clean_data(cur_ch.name),
p_id=cur_ch.id, person=[person], plays_self=cur_ch.plays_self,
thumb_url=cur_ch.image and cur_ch.image.get('medium')
))
if character_person_ids:
for cur_ch, cur_p_ids in iteritems(character_person_ids):
if cur_p_ids:
char = next((mc for mc in ti_show.cast[RoleTypes.ActorMain] if mc.id == cur_ch),
None) # type: Optional[TVInfoCharacter]
if char:
char.person = [p for p in char.person if p.id not in cur_p_ids]
if show_data.cast:
ti_show.actors = [
{'character': {'id': ch.id,
'name': clean_data(ch.name),
'url': 'https://www.tvmaze.com/character/view?id=%s' % ch.id,
'image': ch.image and ch.image.get('original'),
},
'person': {'id': ch.person and ch.person.id,
'name': ch.person and clean_data(ch.person.name),
'url': ch.person and 'https://www.tvmaze.com/person/view?id=%s' % ch.person.id,
'image': ch.person and ch.person.image and ch.person.image.get('original'),
'birthday': None, # not sure about format
'deathday': None, # not sure about format
'gender': ch.person and ch.person.gender and ch.person.gender,
'country': ch.person and ch.person.country and
clean_data(ch.person.country.get('name')),
},
} for ch in show_data.cast.characters]
if show_data.crew:
for cur_cw in show_data.crew:
rt = crew_type_names.get(cur_cw.type.lower(), RoleTypes.CrewOther)
ti_show.crew[rt].append(
Crew(p_id=cur_cw.person.id, name=clean_data(cur_cw.person.name),
image=cur_cw.person.image and cur_cw.person.image.get('original'),
gender=cur_cw.person.gender,
birthdate=cur_cw.person.birthday, deathdate=cur_cw.person.death_day,
country=cur_cw.person.country and cur_cw.person.country.get('name'),
country_code=cur_cw.person.country and clean_data(cur_cw.person.country.get('code')),
country_timezone=cur_cw.person.country
and clean_data(cur_cw.person.country.get('timezone')),
crew_type_name=cur_cw.type,
)
) )
if show_data.externals: if get_ep_info and not getattr(self.ti_shows.get(sid), 'ep_loaded', False):
ti_show.ids = TVInfoIDs(tvdb=show_data.externals.get('thetvdb'),
rage=show_data.externals.get('tvrage'),
imdb=clean_data(show_data.externals.get('imdb') and
try_int(show_data.externals.get('imdb').replace('tt', ''), None)))
if show_data.network:
self._set_network(ti_show, show_data.network, False)
elif show_data.web_channel:
self._set_network(ti_show, show_data.web_channel, True)
if get_ep_info and not getattr(self.shows.get(sid), 'ep_loaded', False):
log.debug('Getting all episodes of %s' % sid) log.debug('Getting all episodes of %s' % sid)
if None is show_data: if None is show_data:
show_data = self._get_tvm_show(sid, get_ep_info) show_data = self._get_tvm_show(sid, get_ep_info)
@ -509,47 +397,262 @@ class TvMaze(TVInfoBase):
# type: (...) -> Dict[integer_types, integer_types] # type: (...) -> Dict[integer_types, integer_types]
return {sid: v.seconds_since_epoch for sid, v in iteritems(tvmaze.show_updates().updates)} return {sid: v.seconds_since_epoch for sid, v in iteritems(tvmaze.show_updates().updates)}
@staticmethod def _convert_person(self, tvmaze_person_obj):
def _convert_person(person_obj):
# type: (tvmaze.Person) -> TVInfoPerson # type: (tvmaze.Person) -> TVInfoPerson
ch = [] ch = []
for c in person_obj.castcredits or []: _dupes = []
show = TVInfoShow() for c in tvmaze_person_obj.castcredits or []:
show.seriesname = clean_data(c.show.name) ti_show = TVInfoShow()
show.id = c.show.id ti_show.seriesname = clean_data(c.show.name)
show.firstaired = clean_data(c.show.premiered) ti_show.id = c.show.id
show.ids = TVInfoIDs(ids={TVINFO_TVMAZE: show.id}) ti_show.firstaired = clean_data(c.show.premiered)
show.overview = clean_data(c.show.summary) ti_show.ids = TVInfoIDs(ids={TVINFO_TVMAZE: ti_show.id})
show.status = clean_data(c.show.status) ti_show.overview = clean_data(c.show.summary)
ti_show.status = clean_data(c.show.status)
net = c.show.network or c.show.web_channel net = c.show.network or c.show.web_channel
if net: if net:
show.network = clean_data(net.name) ti_show.network = clean_data(net.name)
show.network_id = net.maze_id ti_show.network_id = net.maze_id
show.network_country = clean_data(net.country) ti_show.network_country = clean_data(net.country)
show.network_timezone = clean_data(net.timezone) ti_show.network_country_code = clean_data(net.code)
show.network_country_code = clean_data(net.code) ti_show.network_timezone = clean_data(net.timezone)
show.network_is_stream = None is not c.show.web_channel ti_show.network_is_stream = None is not c.show.web_channel
ch.append(TVInfoCharacter(name=clean_data(c.character.name), show=show)) ch.append(TVInfoCharacter(name=clean_data(c.character.name), ti_show=ti_show, episode_count=1))
try: try:
birthdate = person_obj.birthday and tz_p.parse(person_obj.birthday).date() birthdate = tvmaze_person_obj.birthday and tz_p.parse(tvmaze_person_obj.birthday).date()
except (BaseException, Exception): except (BaseException, Exception):
birthdate = None birthdate = None
try: try:
deathdate = person_obj.death_day and tz_p.parse(person_obj.death_day).date() deathdate = tvmaze_person_obj.death_day and tz_p.parse(tvmaze_person_obj.death_day).date()
except (BaseException, Exception): except (BaseException, Exception):
deathdate = None deathdate = None
return TVInfoPerson(p_id=person_obj.id, name=clean_data(person_obj.name),
image=person_obj.image and person_obj.image.get('original'), _ti_person_obj = TVInfoPerson(
gender=PersonGenders.named.get(person_obj.gender and person_obj.gender.lower(), p_id=tvmaze_person_obj.id, name=clean_data(tvmaze_person_obj.name),
image=tvmaze_person_obj.image and tvmaze_person_obj.image.get('original'),
gender=PersonGenders.named.get(tvmaze_person_obj.gender and tvmaze_person_obj.gender.lower(),
PersonGenders.unknown), PersonGenders.unknown),
birthdate=birthdate, deathdate=deathdate, birthdate=birthdate, deathdate=deathdate,
country=person_obj.country and clean_data(person_obj.country.get('name')), country=tvmaze_person_obj.country and clean_data(tvmaze_person_obj.country.get('name')),
country_code=person_obj.country and clean_data(person_obj.country.get('code')), country_code=tvmaze_person_obj.country and clean_data(tvmaze_person_obj.country.get('code')),
country_timezone=person_obj.country and clean_data(person_obj.country.get('timezone')), country_timezone=tvmaze_person_obj.country and clean_data(tvmaze_person_obj.country.get('timezone')),
thumb_url=person_obj.image and person_obj.image.get('medium'), thumb_url=tvmaze_person_obj.image and tvmaze_person_obj.image.get('medium'),
url=person_obj.url, ids={TVINFO_TVMAZE: person_obj.id}, characters=ch url=tvmaze_person_obj.url, ids=TVInfoIDs(ids={TVINFO_TVMAZE: tvmaze_person_obj.id})
) )
for (c_t, regular) in [(tvmaze_person_obj.castcredits or [], True),
(tvmaze_person_obj.guestcastcredits or [], False)]:
for c in c_t: # type: tvmaze.CastCredit
_show = c.show or c.episode.show
_clean_char_name = clean_data(c.character.name)
ti_show = TVInfoShow()
if None is not _show:
_clean_show_name = clean_data(_show.name)
_clean_show_id = clean_data(_show.id)
_cur_dup = (_clean_char_name, _clean_show_id)
if _cur_dup in _dupes:
_co = next((_c for _c in ch if _clean_show_id == _c.ti_show.id
and _c.name == _clean_char_name), None)
if None is not _co:
ti_show = _co.ti_show
_co.episode_count += 1
if not regular:
ep_no = c.episode.episode_number or 0
_co.guest_episodes_numbers.setdefault(c.episode.season_number, []).append(ep_no)
if c.episode.season_number not in ti_show:
season = TVInfoSeason(show=ti_show, number=c.episode.season_number)
ti_show[c.episode.season_number] = season
else:
season = ti_show[c.episode.season_number]
episode = self._make_episode(c.episode, show_obj=ti_show)
episode.season = season
ti_show[c.episode.season_number][ep_no] = episode
continue
else:
_dupes.append(_cur_dup)
ti_show.seriesname = clean_data(_show.name)
ti_show.id = _show.id
ti_show.firstaired = clean_data(_show.premiered)
ti_show.ids = TVInfoIDs(ids={TVINFO_TVMAZE: ti_show.id})
ti_show.overview = enforce_type(clean_data(_show.summary), str, '')
ti_show.status = clean_data(_show.status)
net = _show.network or _show.web_channel
if net:
ti_show.network = clean_data(net.name)
ti_show.network_id = net.maze_id
ti_show.network_country = clean_data(net.country)
ti_show.network_timezone = clean_data(net.timezone)
ti_show.network_country_code = clean_data(net.code)
ti_show.network_is_stream = None is not _show.web_channel
if c.episode:
ti_show.show_loaded = False
ti_show.load_method = self._show_info_loader
season = TVInfoSeason(show=ti_show, number=c.episode.season_number)
ti_show[c.episode.season_number] = season
episode = self._make_episode(c.episode, show_obj=ti_show)
episode.season = season
ti_show[c.episode.season_number][c.episode.episode_number or 0] = episode
if not regular:
_g_kw = {'guest_episodes_numbers': {c.episode.season_number: [c.episode.episode_number or 0]}}
else:
_g_kw = {}
ch.append(TVInfoCharacter(name=_clean_char_name, ti_show=ti_show, regular=regular, episode_count=1,
person=[_ti_person_obj], **_g_kw))
_ti_person_obj.characters = ch
return _ti_person_obj
def _show_info_loader(self, show_id, show_data=None, show_obj=None, load_images=True, load_actors=True):
# type: (int, TVMazeShow, TVInfoShow, bool, bool) -> TVInfoShow
try:
_s_d = show_data or tvmaze.show_main_info(show_id, embed='cast')
if _s_d:
if None is not show_obj:
_s_o = show_obj
else:
_s_o = TVInfoShow()
show_dict = _s_o.__dict__
for k, v in iteritems(show_dict):
if k not in ('cast', 'crew', 'images', 'aliases', 'rating'):
show_dict[k] = getattr(_s_d, show_map.get(k, k), clean_data(show_dict[k]))
_s_o.aliases = [clean_data(a.name) for a in _s_d.akas]
_s_o.runtime = _s_d.average_runtime or _s_d.runtime
p_set = False
if _s_d.image:
p_set = True
_s_o.poster = _s_d.image.get('original')
_s_o.poster_thumb = _s_d.image.get('medium')
if load_images and \
not all(getattr(_s_o, '%s_loaded' % t, False) for t in ('poster', 'banner', 'fanart')):
if _s_d.images:
_s_o.poster_loaded = True
_s_o.banner_loaded = True
_s_o.fanart_loaded = True
self._set_images(_s_o, _s_d, p_set)
if _s_d.schedule:
if 'time' in _s_d.schedule:
_s_o.airs_time = _s_d.schedule['time']
try:
h, m = _s_d.schedule['time'].split(':')
h, m = try_int(h, None), try_int(m, None)
if None is not h and None is not m:
_s_o.time = datetime.time(hour=h, minute=m)
except (BaseException, Exception):
pass
if 'days' in _s_d.schedule:
_s_o.airs_dayofweek = ', '.join(_s_d.schedule['days'])
if load_actors and not _s_o.actors_loaded:
if _s_d.cast:
character_person_ids = {}
for cur_ch in _s_o.cast[RoleTypes.ActorMain]:
character_person_ids.setdefault(cur_ch.id, []).extend([p.id for p in cur_ch.person])
for cur_ch in _s_d.cast.characters:
existing_character = next(
(c for c in _s_o.cast[RoleTypes.ActorMain] if c.id == cur_ch.id),
None) # type: Optional[TVInfoCharacter]
person = self._convert_person(cur_ch.person)
if existing_character:
existing_person = next((p for p in existing_character.person
if person.id == p.ids.get(TVINFO_TVMAZE)),
None) # type: TVInfoPerson
if existing_person:
try:
character_person_ids[cur_ch.id].remove(existing_person.id)
except (BaseException, Exception):
print('error')
pass
(existing_person.p_id, existing_person.name, existing_person.image,
existing_person.gender,
existing_person.birthdate, existing_person.deathdate, existing_person.country,
existing_person.country_code, existing_person.country_timezone,
existing_person.thumb_url,
existing_person.url, existing_person.ids) = \
(cur_ch.person.id, clean_data(cur_ch.person.name),
cur_ch.person.image and cur_ch.person.image.get('original'),
PersonGenders.named.get(
cur_ch.person.gender and cur_ch.person.gender.lower(),
PersonGenders.unknown),
person.birthdate, person.deathdate,
cur_ch.person.country and clean_data(cur_ch.person.country.get('name')),
cur_ch.person.country and clean_data(cur_ch.person.country.get('code')),
cur_ch.person.country and clean_data(cur_ch.person.country.get('timezone')),
cur_ch.person.image and cur_ch.person.image.get('medium'),
cur_ch.person.url, {TVINFO_TVMAZE: cur_ch.person.id})
else:
existing_character.person.append(person)
else:
_s_o.cast[RoleTypes.ActorMain].append(
TVInfoCharacter(image=cur_ch.image and cur_ch.image.get('original'),
name=clean_data(cur_ch.name),
ids=TVInfoIDs({TVINFO_TVMAZE: cur_ch.id}),
p_id=cur_ch.id, person=[person], plays_self=cur_ch.plays_self,
thumb_url=cur_ch.image and cur_ch.image.get('medium'),
ti_show=_s_o
))
if character_person_ids:
for cur_ch, cur_p_ids in iteritems(character_person_ids):
if cur_p_ids:
char = next((mc for mc in _s_o.cast[RoleTypes.ActorMain] if mc.id == cur_ch),
None) # type: Optional[TVInfoCharacter]
if char:
char.person = [p for p in char.person if p.id not in cur_p_ids]
if _s_d.cast:
_s_o.actors = [
{'character': {'id': ch.id,
'name': clean_data(ch.name),
'url': 'https://www.tvmaze.com/character/view?id=%s' % ch.id,
'image': ch.image and ch.image.get('original'),
},
'person': {'id': ch.person and ch.person.id,
'name': ch.person and clean_data(ch.person.name),
'url': ch.person and 'https://www.tvmaze.com/person/view?id=%s' % ch.person.id,
'image': ch.person and ch.person.image and ch.person.image.get('original'),
'birthday': None, # not sure about format
'deathday': None, # not sure about format
'gender': ch.person and ch.person.gender and ch.person.gender,
'country': ch.person and ch.person.country and
clean_data(ch.person.country.get('name')),
},
} for ch in _s_d.cast.characters]
if _s_d.crew:
for cur_cw in _s_d.crew:
rt = crew_type_names.get(cur_cw.type.lower(), RoleTypes.CrewOther)
_s_o.crew[rt].append(
Crew(p_id=cur_cw.person.id, name=clean_data(cur_cw.person.name),
image=cur_cw.person.image and cur_cw.person.image.get('original'),
gender=cur_cw.person.gender,
birthdate=cur_cw.person.birthday, deathdate=cur_cw.person.death_day,
country=cur_cw.person.country and cur_cw.person.country.get('name'),
country_code=cur_cw.person.country and clean_data(
cur_cw.person.country.get('code')),
country_timezone=cur_cw.person.country
and clean_data(cur_cw.person.country.get('timezone')),
crew_type_name=cur_cw.type,
)
)
if _s_d.externals:
_s_o.ids = TVInfoIDs(tvdb=_s_d.externals.get('thetvdb'),
rage=_s_d.externals.get('tvrage'),
imdb=clean_data(_s_d.externals.get('imdb') and
try_int(_s_d.externals.get('imdb').replace('tt', ''),
None)))
if _s_d.network:
self._set_network(_s_o, _s_d.network, False)
elif _s_d.web_channel:
self._set_network(_s_o, _s_d.web_channel, True)
return _s_o
except (BaseException, Exception):
pass
def _search_person(self, name=None, ids=None): def _search_person(self, name=None, ids=None):
# type: (AnyStr, Dict[integer_types, integer_types]) -> List[TVInfoPerson] # type: (AnyStr, Dict[integer_types, integer_types]) -> List[TVInfoPerson]
urls, result, ids = [], [], ids or {} urls, result, ids = [], [], ids or {}
@ -597,27 +700,31 @@ class TvMaze(TVInfoBase):
return self._convert_person(p) return self._convert_person(p)
def get_premieres(self, **kwargs): def get_premieres(self, **kwargs):
# type: (...) -> List[TVInfoEpisode] # type: (...) -> List[TVInfoShow]
return self._filtered_schedule(**kwargs).get('premieres') return [_e.show for _e in self._filtered_schedule(**kwargs).get('premieres')]
def get_returning(self, **kwargs): def get_returning(self, **kwargs):
# type: (...) -> List[TVInfoEpisode] # type: (...) -> List[TVInfoShow]
return self._filtered_schedule(**kwargs).get('returning') return [_e.show for _e in self._filtered_schedule(**kwargs).get('returning')]
def _make_episode(self, episode_data, show_data=None, get_images=False, get_akas=False): def _make_episode(self, episode_data, show_data=None, get_images=False, get_akas=False, show_obj=None):
# type: (TVMazeEpisode, TVMazeShow, bool, bool) -> TVInfoEpisode # type: (TVMazeEpisode, TVMazeShow, bool, bool, TVInfoShow) -> TVInfoEpisode
""" """
make out of TVMazeEpisode object and optionally TVMazeShow a TVInfoEpisode make out of TVMazeEpisode object and optionally TVMazeShow a TVInfoEpisode
""" """
if None is not show_obj:
ti_show = show_obj
else:
ti_show = TVInfoShow() ti_show = TVInfoShow()
ti_show.seriesname = clean_data(show_data.name) ti_show.seriesname = clean_data(show_data.name)
ti_show.id = show_data.maze_id ti_show.id = show_data.maze_id
ti_show.seriesid = ti_show.id ti_show.seriesid = ti_show.id
ti_show.language = clean_data(show_data.language) ti_show.language = clean_data(show_data.language)
ti_show.overview = clean_data(show_data.summary) ti_show.overview = enforce_type(clean_data(show_data.summary), str, '')
ti_show.firstaired = clean_data(show_data.premiered) ti_show.firstaired = clean_data(show_data.premiered)
ti_show.runtime = show_data.average_runtime or show_data.runtime ti_show.runtime = show_data.average_runtime or show_data.runtime
ti_show.vote_average = show_data.rating and show_data.rating.get('average') ti_show.vote_average = show_data.rating and show_data.rating.get('average')
ti_show.rating = ti_show.vote_average
ti_show.popularity = show_data.weight ti_show.popularity = show_data.weight
ti_show.genre_list = clean_data(show_data.genres or []) ti_show.genre_list = clean_data(show_data.genres or [])
ti_show.genre = '|'.join(ti_show.genre_list).lower() ti_show.genre = '|'.join(ti_show.genre_list).lower()
@ -629,7 +736,7 @@ class TvMaze(TVInfoBase):
ti_show.poster = show_data.image and show_data.image.get('original') ti_show.poster = show_data.image and show_data.image.get('original')
if get_akas: if get_akas:
ti_show.aliases = [clean_data(a.name) for a in show_data.akas] ti_show.aliases = [clean_data(a.name) for a in show_data.akas]
if 'days' in show_data.schedule: if show_data.schedule and 'days' in show_data.schedule:
ti_show.airs_dayofweek = ', '.join(clean_data(show_data.schedule['days'])) ti_show.airs_dayofweek = ', '.join(clean_data(show_data.schedule['days']))
network = show_data.network or show_data.web_channel network = show_data.network or show_data.web_channel
if network: if network:
@ -652,9 +759,12 @@ class TvMaze(TVInfoBase):
ti_episode = TVInfoEpisode(show=ti_show) ti_episode = TVInfoEpisode(show=ti_show)
ti_episode.id = episode_data.maze_id ti_episode.id = episode_data.maze_id
ti_episode.seasonnumber = episode_data.season_number ti_episode.seasonnumber = episode_data.season_number
ti_episode.episodenumber = episode_data.episode_number ti_episode.episodenumber = episode_data.episode_number or 0
ti_episode.episodename = clean_data(episode_data.title) ti_episode.episodename = clean_data(episode_data.title)
ti_episode.airtime = clean_data(episode_data.airtime) try:
ti_episode.airtime = datetime.time.fromisoformat(clean_data(episode_data.airtime))
except (BaseException, Exception):
ti_episode.airtime = None
ti_episode.firstaired = clean_data(episode_data.airdate) ti_episode.firstaired = clean_data(episode_data.airdate)
if episode_data.airstamp: if episode_data.airstamp:
try: try:
@ -665,8 +775,13 @@ class TvMaze(TVInfoBase):
ti_episode.filename = episode_data.image and (episode_data.image.get('original') or ti_episode.filename = episode_data.image and (episode_data.image.get('original') or
episode_data.image.get('medium')) episode_data.image.get('medium'))
ti_episode.is_special = episode_data.is_special() ti_episode.is_special = episode_data.is_special()
ti_episode.overview = clean_data(episode_data.summary) ti_episode.overview = enforce_type(clean_data(episode_data.summary), str, '')
ti_episode.runtime = episode_data.runtime ti_episode.runtime = episode_data.runtime
if ti_episode.seasonnumber not in ti_show:
season = TVInfoSeason(show=ti_show, number=ti_episode.seasonnumber)
ti_show[ti_episode.seasonnumber] = season
ti_episode.season = season
ti_show[ti_episode.seasonnumber][ti_episode.episodenumber] = ti_episode
return ti_episode return ti_episode
def _filtered_schedule(self, **kwargs): def _filtered_schedule(self, **kwargs):

View file

@ -1,29 +1,38 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import asyncio
import os import os
from functools import partial
from itertools import chain from itertools import chain
from . import common from . import common
from .conversion import convert_between from .conversion import convert_between
@ -43,11 +52,6 @@ from .plugins.NotifyBase import NotifyBase
from . import plugins from . import plugins
from . import __version__ from . import __version__
# Python v3+ support code made importable, so it can remain backwards
# compatible with Python v2
# TODO: Review after dropping support for Python 2.
from . import py3compat
class Apprise: class Apprise:
""" """
@ -369,91 +373,118 @@ class Apprise:
such as turning a \n into an actual new line, etc. such as turning a \n into an actual new line, etc.
""" """
return py3compat.asyncio.tosync( try:
self.async_notify( # Process arguments and build synchronous and asynchronous calls
# (this step can throw internal errors).
sync_partials, async_cors = self._create_notify_calls(
body, title, body, title,
notify_type=notify_type, body_format=body_format, notify_type=notify_type, body_format=body_format,
tag=tag, match_always=match_always, attach=attach, tag=tag, match_always=match_always, attach=attach,
interpret_escapes=interpret_escapes, interpret_escapes=interpret_escapes
),
debug=self.debug
) )
def async_notify(self, *args, **kwargs): except TypeError:
# No notifications sent, and there was an internal error.
return False
if not sync_partials and not async_cors:
# Nothing to send
return None
sync_result = Apprise._notify_all(*sync_partials)
if async_cors:
# A single coroutine sends all asynchronous notifications in
# parallel.
all_cor = Apprise._async_notify_all(*async_cors)
try:
# Python <3.7 automatically starts an event loop if there isn't
# already one for the main thread.
loop = asyncio.get_event_loop()
except RuntimeError:
# Python >=3.7 raises this exception if there isn't already an
# event loop. So, we can spin up our own.
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.set_debug(self.debug)
# Run the coroutine and wait for the result.
async_result = loop.run_until_complete(all_cor)
# Clean up the loop.
loop.close()
asyncio.set_event_loop(None)
else:
old_debug = loop.get_debug()
loop.set_debug(self.debug)
# Run the coroutine and wait for the result.
async_result = loop.run_until_complete(all_cor)
loop.set_debug(old_debug)
else:
async_result = True
return sync_result and async_result
async def async_notify(self, *args, **kwargs):
""" """
Send a notification to all the plugins previously loaded, for Send a notification to all the plugins previously loaded, for
asynchronous callers. This method is an async method that should be asynchronous callers.
awaited on, even if it is missing the async keyword in its signature.
(This is omitted to preserve syntax compatibility with Python 2.)
The arguments are identical to those of Apprise.notify(). The arguments are identical to those of Apprise.notify().
""" """
try: try:
coroutines = list( # Process arguments and build synchronous and asynchronous calls
self._notifyall( # (this step can throw internal errors).
Apprise._notifyhandlerasync, *args, **kwargs)) sync_partials, async_cors = self._create_notify_calls(
*args, **kwargs)
except TypeError: except TypeError:
# No notifications sent, and there was an internal error. # No notifications sent, and there was an internal error.
return py3compat.asyncio.toasyncwrapvalue(False)
else:
if len(coroutines) > 0:
# All notifications sent, return False if any failed.
return py3compat.asyncio.notify(coroutines)
else:
# No notifications sent.
return py3compat.asyncio.toasyncwrapvalue(None)
@staticmethod
def _notifyhandler(server, **kwargs):
"""
The synchronous notification sender. Returns True if the notification
sent successfully.
"""
try:
# Send notification
return server.notify(**kwargs)
except TypeError:
# These our our internally thrown notifications
return False return False
except Exception: if not sync_partials and not async_cors:
# A catch all so we don't have to abort early # Nothing to send
# just because one of our plugins has a bug in it. return None
logger.exception("Unhandled Notification Exception")
return False
@staticmethod sync_result = Apprise._notify_all(*sync_partials)
def _notifyhandlerasync(server, **kwargs): async_result = await Apprise._async_notify_all(*async_cors)
""" return sync_result and async_result
The asynchronous notification sender. Returns a coroutine that yields
True if the notification sent successfully.
"""
if server.asset.async_mode: def _create_notify_calls(self, *args, **kwargs):
return server.async_notify(**kwargs)
else:
# Send the notification immediately, and wrap the result in a
# coroutine.
status = Apprise._notifyhandler(server, **kwargs)
return py3compat.asyncio.toasyncwrapvalue(status)
def _notifyall(self, handler, body, title='',
notify_type=common.NotifyType.INFO, body_format=None,
tag=common.MATCH_ALL_TAG, match_always=True, attach=None,
interpret_escapes=None):
""" """
Creates notifications for all the plugins loaded. Creates notifications for all the plugins loaded.
Returns a generator that calls handler for each notification. The first Returns a list of synchronous calls (partial functions with no
and only argument supplied to handler is the server, and the keyword arguments required) for plugins with async disabled and a list of
arguments are exactly as they would be passed to server.notify(). asynchronous calls (coroutines) for plugins with async enabled.
"""
all_calls = list(self._create_notify_gen(*args, **kwargs))
# Split into synchronous partials and asynchronous coroutines.
sync_partials, async_cors = [], []
for notify in all_calls:
if asyncio.iscoroutine(notify):
async_cors.append(notify)
else:
sync_partials.append(notify)
return sync_partials, async_cors
def _create_notify_gen(self, body, title='',
notify_type=common.NotifyType.INFO,
body_format=None, tag=common.MATCH_ALL_TAG,
match_always=True, attach=None,
interpret_escapes=None):
"""
Internal generator function for _create_notify_calls().
""" """
if len(self) == 0: if len(self) == 0:
@ -546,14 +577,67 @@ class Apprise:
logger.error(msg) logger.error(msg)
raise TypeError(msg) raise TypeError(msg)
yield handler( kwargs = dict(
server,
body=conversion_body_map[server.notify_format], body=conversion_body_map[server.notify_format],
title=conversion_title_map[server.notify_format], title=conversion_title_map[server.notify_format],
notify_type=notify_type, notify_type=notify_type,
attach=attach, attach=attach,
body_format=body_format, body_format=body_format
) )
if server.asset.async_mode:
yield server.async_notify(**kwargs)
else:
yield partial(server.notify, **kwargs)
@staticmethod
def _notify_all(*partials):
"""
Process a list of synchronous notify() calls.
"""
success = True
for notify in partials:
try:
# Send notification
result = notify()
success = success and result
except TypeError:
# These are our internally thrown notifications.
success = False
except Exception:
# A catch all so we don't have to abort early
# just because one of our plugins has a bug in it.
logger.exception("Unhandled Notification Exception")
success = False
return success
@staticmethod
async def _async_notify_all(*cors):
"""
Process a list of asynchronous async_notify() calls.
"""
# Create log entry
logger.info('Notifying %d service(s) asynchronously.', len(cors))
results = await asyncio.gather(*cors, return_exceptions=True)
if any(isinstance(status, Exception)
and not isinstance(status, TypeError) for status in results):
# A catch all so we don't have to abort early just because
# one of our plugins has a bug in it.
logger.exception("Unhandled Notification Exception")
return False
if any(isinstance(status, TypeError) for status in results):
# These are our internally thrown notifications.
return False
return all(results)
def details(self, lang=None, show_requirements=False, show_disabled=False): def details(self, lang=None, show_requirements=False, show_disabled=False):
""" """

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
from uuid import uuid4 from uuid import uuid4

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from . import attachment from . import attachment
from . import URLBase from . import URLBase

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from . import config from . import config
from . import ConfigBase from . import ConfigBase

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import ctypes import ctypes
import locale import locale

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
from .logger import logger from .logger import logger

View file

@ -1,33 +1,40 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
__title__ = 'Apprise' __title__ = 'Apprise'
__version__ = '1.2.1' __version__ = '1.3.0'
__author__ = 'Chris Caron' __author__ = 'Chris Caron'
__license__ = 'MIT' __license__ = 'BSD'
__copywrite__ = 'Copyright (C) 2022 Chris Caron <lead2gold@gmail.com>' __copywrite__ = 'Copyright (C) 2023 Chris Caron <lead2gold@gmail.com>'
__email__ = 'lead2gold@gmail.com' __email__ = 'lead2gold@gmail.com'
__status__ = 'Production' __status__ = 'Production'

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os import os
import time import time

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
import os import os

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
import os import os

View file

@ -1,30 +1,36 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
from os import listdir from os import listdir
from os.path import dirname from os.path import dirname
from os.path import abspath from os.path import abspath

View file

@ -1,28 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# we mirror our base purely for the ability to reset everything; this # we mirror our base purely for the ability to reset everything; this
# is generally only used in testing and should not be used by developers # is generally only used in testing and should not be used by developers

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2020 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os import os
import re import re

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
import os import os

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
import requests import requests

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2020 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from .ConfigBase import ConfigBase from .ConfigBase import ConfigBase
from ..AppriseLocale import gettext_lazy as _ from ..AppriseLocale import gettext_lazy as _

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
from os import listdir from os import listdir

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
#from markdown import markdown #from markdown import markdown

View file

@ -1,27 +1,35 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from ..plugins.NotifyBase import NotifyBase from ..plugins.NotifyBase import NotifyBase
from ..utils import URL_DETAILS_RE from ..utils import URL_DETAILS_RE
from ..utils import parse_url from ..utils import parse_url

View file

@ -1,27 +1,35 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from .notify import notify from .notify import notify

View file

@ -1,27 +1,35 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from .CustomNotifyPlugin import CustomNotifyPlugin from .CustomNotifyPlugin import CustomNotifyPlugin

View file

@ -1,14 +1,14 @@
# Translations template for apprise. # Translations template for apprise.
# Copyright (C) 2022 Chris Caron # Copyright (C) 2023 Chris Caron
# This file is distributed under the same license as the apprise project. # This file is distributed under the same license as the apprise project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022. # FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: apprise 1.2.1\n" "Project-Id-Version: apprise 1.3.0\n"
"Report-Msgid-Bugs-To: lead2gold@gmail.com\n" "Report-Msgid-Bugs-To: lead2gold@gmail.com\n"
"POT-Creation-Date: 2022-12-28 09:43-0500\n" "POT-Creation-Date: 2023-02-22 17:31-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -50,6 +50,9 @@ msgstr ""
msgid "Account SID" msgid "Account SID"
msgstr "" msgstr ""
msgid "Action"
msgstr ""
msgid "Add Tokens" msgid "Add Tokens"
msgstr "" msgstr ""
@ -83,6 +86,9 @@ msgstr ""
msgid "Attach" msgid "Attach"
msgstr "" msgstr ""
msgid "Attach File As"
msgstr ""
msgid "Attach Filename" msgid "Attach Filename"
msgstr "" msgstr ""
@ -92,6 +98,9 @@ msgstr ""
msgid "Authentication Key" msgid "Authentication Key"
msgstr "" msgstr ""
msgid "Authentication Type"
msgstr ""
msgid "Authorization Token" msgid "Authorization Token"
msgstr "" msgstr ""
@ -305,6 +314,9 @@ msgstr ""
msgid "Include Segment" msgid "Include Segment"
msgstr "" msgstr ""
msgid "Integration ID"
msgstr ""
msgid "Is Ad?" msgid "Is Ad?"
msgstr "" msgstr ""
@ -353,6 +365,9 @@ msgstr ""
msgid "Message Type" msgid "Message Type"
msgstr "" msgstr ""
msgid "Meta Extras"
msgstr ""
msgid "Modal" msgid "Modal"
msgstr "" msgstr ""
@ -658,6 +673,9 @@ msgstr ""
msgid "Text To Speech" msgid "Text To Speech"
msgstr "" msgstr ""
msgid "Third Party ID"
msgstr ""
msgid "Thread ID" msgid "Thread ID"
msgstr "" msgstr ""
@ -715,6 +733,9 @@ msgstr ""
msgid "Use Session" msgid "Use Session"
msgstr "" msgstr ""
msgid "User Email"
msgstr ""
msgid "User ID" msgid "User ID"
msgstr "" msgstr ""

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os import os
import logging import logging

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
import requests import requests

View file

@ -1,27 +1,35 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# #
# API: https://github.com/Finb/bark-server/blob/master/docs/API_V2.md#python # API: https://github.com/Finb/bark-server/blob/master/docs/API_V2.md#python
# #

View file

@ -1,29 +1,38 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import asyncio
import re import re
from functools import partial
from ..URLBase import URLBase from ..URLBase import URLBase
from ..common import NotifyType from ..common import NotifyType
@ -36,12 +45,7 @@ from ..AppriseLocale import gettext_lazy as _
from ..AppriseAttachment import AppriseAttachment from ..AppriseAttachment import AppriseAttachment
# Wrap our base with the asyncio wrapper class NotifyBase(URLBase):
from ..py3compat.asyncio import AsyncNotifyBase
BASE_OBJECT = AsyncNotifyBase
class NotifyBase(BASE_OBJECT):
""" """
This is the base class for all notification services This is the base class for all notification services
""" """
@ -267,19 +271,64 @@ class NotifyBase(BASE_OBJECT):
color_type=color_type, color_type=color_type,
) )
def notify(self, body, title=None, notify_type=NotifyType.INFO, def notify(self, *args, **kwargs):
overflow=None, attach=None, body_format=None, **kwargs):
""" """
Performs notification Performs notification
"""
try:
# Build a list of dictionaries that can be used to call send().
send_calls = list(self._build_send_calls(*args, **kwargs))
except TypeError:
# Internal error
return False
else:
# Loop through each call, one at a time. (Use a list rather than a
# generator to call all the partials, even in case of a failure.)
the_calls = [self.send(**kwargs2) for kwargs2 in send_calls]
return all(the_calls)
async def async_notify(self, *args, **kwargs):
"""
Performs notification for asynchronous callers
"""
try:
# Build a list of dictionaries that can be used to call send().
send_calls = list(self._build_send_calls(*args, **kwargs))
except TypeError:
# Internal error
return False
else:
loop = asyncio.get_event_loop()
# Wrap each call in a coroutine that uses the default executor.
# TODO: In the future, allow plugins to supply a native
# async_send() method.
async def do_send(**kwargs2):
send = partial(self.send, **kwargs2)
result = await loop.run_in_executor(None, send)
return result
# gather() all calls in parallel.
the_cors = (do_send(**kwargs2) for kwargs2 in send_calls)
return all(await asyncio.gather(*the_cors))
def _build_send_calls(self, body, title=None,
notify_type=NotifyType.INFO, overflow=None,
attach=None, body_format=None, **kwargs):
"""
Get a list of dictionaries that can be used to call send() or
(in the future) async_send().
""" """
if not self.enabled: if not self.enabled:
# Deny notifications issued to services that are disabled # Deny notifications issued to services that are disabled
self.logger.warning( msg = f"{self.service_name} is currently disabled on this system."
"{} is currently disabled on this system.".format( self.logger.warning(msg)
self.service_name)) raise TypeError(msg)
return False
# Prepare attachments if required # Prepare attachments if required
if attach is not None and not isinstance(attach, AppriseAttachment): if attach is not None and not isinstance(attach, AppriseAttachment):
@ -288,7 +337,7 @@ class NotifyBase(BASE_OBJECT):
except TypeError: except TypeError:
# bad attachments # bad attachments
return False raise
# Handle situations where the title is None # Handle situations where the title is None
title = '' if not title else title title = '' if not title else title
@ -299,14 +348,11 @@ class NotifyBase(BASE_OBJECT):
body_format=body_format): body_format=body_format):
# Send notification # Send notification
if not self.send(body=chunk['body'], title=chunk['title'], yield dict(
body=chunk['body'], title=chunk['title'],
notify_type=notify_type, attach=attach, notify_type=notify_type, attach=attach,
body_format=body_format): body_format=body_format
)
# Toggle our return status flag
return False
return True
def _apply_overflow(self, body, title=None, overflow=None, def _apply_overflow(self, body, title=None, overflow=None,
body_format=None): body_format=None):

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
import requests import requests

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# To use this service you will need a BulkSMS account # To use this service you will need a BulkSMS account
# You will need credits (new accounts start with a few) # You will need credits (new accounts start with a few)

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# To use this plugin, simply signup with clicksend: # To use this plugin, simply signup with clicksend:
# https://www.clicksend.com/ # https://www.clicksend.com/

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# To use this service you will need a D7 Networks account from their website # To use this service you will need a D7 Networks account from their website
# at https://d7networks.com/ # at https://d7networks.com/

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import print_function from __future__ import print_function

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# To use this plugin, sign up with Hampager (you need to be a licensed # To use this plugin, sign up with Hampager (you need to be a licensed
# ham radio operator # ham radio operator

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2020 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
import time import time

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# For this to work correctly you need to create a webhook. To do this just # For this to work correctly you need to create a webhook. To do this just
# click on the little gear icon next to the channel you're part of. From # click on the little gear icon next to the channel you're part of. From

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import dataclasses import dataclasses
import re import re

View file

@ -1,30 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# For this plugin to work correct, the Emby server must be set up to allow # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# for remote connections. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Emby Docker configuration: https://hub.docker.com/r/emby/embyserver/ # Emby Docker configuration: https://hub.docker.com/r/emby/embyserver/
# Authentication: https://github.com/MediaBrowser/Emby/wiki/Authentication # Authentication: https://github.com/MediaBrowser/Emby/wiki/Authentication

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Sources # Sources
# - https://dreambox.de/en/ # - https://dreambox.de/en/

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# For this plugin to work correct, the FCM server must be set up to allow # For this plugin to work correct, the FCM server must be set up to allow
# for remote connections. # for remote connections.

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# New priorities are defined here: # New priorities are defined here:
# - https://firebase.google.com/docs/reference/fcm/rest/v1/\ # - https://firebase.google.com/docs/reference/fcm/rest/v1/\

View file

@ -1,27 +1,35 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
class FCMMode: class FCMMode:
""" """
Define the Firebase Cloud Messaging Modes Define the Firebase Cloud Messaging Modes

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# #
# To generate a private key file for your service account: # To generate a private key file for your service account:
# #

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# New priorities are defined here: # New priorities are defined here:
# - https://firebase.google.com/docs/reference/fcm/rest/v1/\ # - https://firebase.google.com/docs/reference/fcm/rest/v1/\

View file

@ -1,26 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CON # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import requests import requests

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# To use this plugin, you need to first access https://dev.flock.com/webhooks # To use this plugin, you need to first access https://dev.flock.com/webhooks
# Specifically https://dev.flock.com/webhooks/incoming # Specifically https://dev.flock.com/webhooks/incoming

View file

@ -1,28 +1,36 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re
import requests import requests
from .NotifyBase import NotifyBase from .NotifyBase import NotifyBase
@ -38,7 +46,8 @@ METHODS = (
'GET', 'GET',
'DELETE', 'DELETE',
'PUT', 'PUT',
'HEAD' 'HEAD',
'PATCH'
) )
@ -47,6 +56,27 @@ class NotifyForm(NotifyBase):
A wrapper for Form Notifications A wrapper for Form Notifications
""" """
# Support
# - file*
# - file?
# - file*name
# - file?name
# - ?file
# - *file
# - file
# The code will convert the ? or * to the digit increments
__attach_as_re = re.compile(
r'((?P<match1>(?P<id1a>[a-z0-9_-]+)?'
r'(?P<wc1>[*?+$:.%]+)(?P<id1b>[a-z0-9_-]+))'
r'|(?P<match2>(?P<id2>[a-z0-9_-]+)(?P<wc2>[*?+$:.%]?)))',
re.IGNORECASE)
# Our count
attach_as_count = '{:02d}'
# the default attach_as value
attach_as_default = f'file{attach_as_count}'
# The default descriptive name associated with the Notification # The default descriptive name associated with the Notification
service_name = 'Form' service_name = 'Form'
@ -111,6 +141,12 @@ class NotifyForm(NotifyBase):
'values': METHODS, 'values': METHODS,
'default': METHODS[0], 'default': METHODS[0],
}, },
'attach-as': {
'name': _('Attach File As'),
'type': 'string',
'default': 'file*',
'map_to': 'attach_as',
},
}) })
# Define any kwargs we're using # Define any kwargs we're using
@ -130,7 +166,7 @@ class NotifyForm(NotifyBase):
} }
def __init__(self, headers=None, method=None, payload=None, params=None, def __init__(self, headers=None, method=None, payload=None, params=None,
**kwargs): attach_as=None, **kwargs):
""" """
Initialize Form Object Initialize Form Object
@ -152,6 +188,36 @@ class NotifyForm(NotifyBase):
self.logger.warning(msg) self.logger.warning(msg)
raise TypeError(msg) raise TypeError(msg)
# Custom File Attachment Over-Ride Support
if not isinstance(attach_as, str):
# Default value
self.attach_as = self.attach_as_default
self.attach_multi_support = True
else:
result = self.__attach_as_re.match(attach_as.strip())
if not result:
msg = 'The attach-as specified ({}) is invalid.'.format(
attach_as)
self.logger.warning(msg)
raise TypeError(msg)
self.attach_as = ''
self.attach_multi_support = False
if result.group('match1'):
if result.group('id1a'):
self.attach_as += result.group('id1a')
self.attach_as += self.attach_as_count
self.attach_multi_support = True
self.attach_as += result.group('id1b')
else: # result.group('match2'):
self.attach_as += result.group('id2')
if result.group('wc2'):
self.attach_as += self.attach_as_count
self.attach_multi_support = True
self.params = {} self.params = {}
if params: if params:
# Store our extra headers # Store our extra headers
@ -192,6 +258,10 @@ class NotifyForm(NotifyBase):
params.update( params.update(
{':{}'.format(k): v for k, v in self.payload_extras.items()}) {':{}'.format(k): v for k, v in self.payload_extras.items()})
if self.attach_as != self.attach_as_default:
# Provide Attach-As extension details
params['attach-as'] = self.attach_as
# Determine Authentication # Determine Authentication
auth = '' auth = ''
if self.user and self.password: if self.user and self.password:
@ -247,7 +317,8 @@ class NotifyForm(NotifyBase):
try: try:
files.append(( files.append((
'file{:02d}'.format(no), ( self.attach_as.format(no)
if self.attach_multi_support else self.attach_as, (
attachment.name, attachment.name,
open(attachment.path, 'rb'), open(attachment.path, 'rb'),
attachment.mimetype) attachment.mimetype)
@ -260,11 +331,10 @@ class NotifyForm(NotifyBase):
self.logger.debug('I/O Exception: %s' % str(e)) self.logger.debug('I/O Exception: %s' % str(e))
return False return False
finally: if not self.attach_multi_support and no > 1:
for file in files: self.logger.warning(
# Ensure all files are closed 'Multiple attachments provided while '
if file[1][1]: 'form:// Multi-Attachment Support not enabled')
file[1][1].close()
# prepare Form Object # prepare Form Object
payload = { payload = {
@ -308,6 +378,9 @@ class NotifyForm(NotifyBase):
elif self.method == 'PUT': elif self.method == 'PUT':
method = requests.put method = requests.put
elif self.method == 'PATCH':
method = requests.patch
elif self.method == 'DELETE': elif self.method == 'DELETE':
method = requests.delete method = requests.delete
@ -396,6 +469,12 @@ class NotifyForm(NotifyBase):
results['params'] = {NotifyForm.unquote(x): NotifyForm.unquote(y) results['params'] = {NotifyForm.unquote(x): NotifyForm.unquote(y)
for x, y in results['qsd-'].items()} for x, y in results['qsd-'].items()}
# Allow Attach-As Support which over-rides the name of the filename
# posted with the form://
# the default is file01, file02, file03, etc
if 'attach-as' in results['qsd'] and len(results['qsd']['attach-as']):
results['attach_as'] = results['qsd']['attach-as']
# Set method if not otherwise set # Set method if not otherwise set
if 'method' in results['qsd'] and len(results['qsd']['method']): if 'method' in results['qsd'] and len(results['qsd']['method']):
results['method'] = NotifyForm.unquote(results['qsd']['method']) results['method'] = NotifyForm.unquote(results['qsd']['method'])

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Once you visit: https://developer.gitter.im/apps you'll get a personal # Once you visit: https://developer.gitter.im/apps you'll get a personal
# access token that will look something like this: # access token that will look something like this:

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import print_function from __future__ import print_function

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# For this to work correctly you need to create a webhook. You'll also # For this to work correctly you need to create a webhook. You'll also
# need a GSuite account (there are free trials if you don't have one) # need a GSuite account (there are free trials if you don't have one)

View file

@ -1,30 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# For this plugin to work correct, the Gotify server must be set up to allow # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# for remote connections. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Gotify Docker configuration: https://hub.docker.com/r/gotify/server # Gotify Docker configuration: https://hub.docker.com/r/gotify/server
# Example: https://github.com/gotify/server/blob/\ # Example: https://github.com/gotify/server/blob/\

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2020 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from .NotifyBase import NotifyBase from .NotifyBase import NotifyBase
from ..URLBase import PrivacyMode from ..URLBase import PrivacyMode

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# For this to work correctly you need to create a webhook. To do this just # For this to work correctly you need to create a webhook. To do this just
# click on the little gear icon next to the channel you're part of. From # click on the little gear icon next to the channel you're part of. From

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# You must generate a "Long-Lived Access Token". This can be done from your # You must generate a "Long-Lived Access Token". This can be done from your
# Home Assistant Profile page. # Home Assistant Profile page.

View file

@ -1,29 +1,35 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# IFTTT (If-This-Then-That) # Apprise - Push Notification Library.
# Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Redistribution and use in source and binary forms, with or without
# All rights reserved. # modification, are permitted provided that the following conditions are met:
# #
# This code is licensed under the MIT License. # 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 2. Redistributions in binary form must reproduce the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer in the documentation
# in the Software without restriction, including without limitation the rights # and/or other materials provided with the distribution.
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 3. Neither the name of the copyright holder nor the names of its
# all copies or substantial portions of the Software. # contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# THE SOFTWARE. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# #
# For this plugin to work, you need to add the Maker applet to your profile # For this plugin to work, you need to add the Maker applet to your profile
# Simply visit https://ifttt.com/search and search for 'Webhooks' # Simply visit https://ifttt.com/search and search for 'Webhooks'

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import requests import requests
import base64 import base64
@ -40,7 +47,8 @@ METHODS = (
'GET', 'GET',
'DELETE', 'DELETE',
'PUT', 'PUT',
'HEAD' 'HEAD',
'PATCH'
) )
@ -308,6 +316,9 @@ class NotifyJSON(NotifyBase):
elif self.method == 'PUT': elif self.method == 'PUT':
method = requests.put method = requests.put
elif self.method == 'PATCH':
method = requests.patch
elif self.method == 'DELETE': elif self.method == 'DELETE':
method = requests.delete method = requests.delete

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Join URL: http://joaoapps.com/join/ # Join URL: http://joaoapps.com/join/
# To use this plugin, you need to first access (make sure your browser allows # To use this plugin, you need to first access (make sure your browser allows

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2020 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# To use this service you will need a Kavenegar account from their website # To use this service you will need a Kavenegar account from their website
# at https://kavenegar.com/ # at https://kavenegar.com/

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# To use this plugin, you must have a Kumulos account set up. Add a client # To use this plugin, you must have a Kumulos account set up. Add a client
# and link it with your phone using the phone app (using your Companion App # and link it with your phone using the phone app (using your Companion App

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2020 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# For LaMetric to work, you need to first setup a custom application on their # For LaMetric to work, you need to first setup a custom application on their
# website. it can be done as follows: # website. it can be done as follows:

View file

@ -1,27 +1,35 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# #
# API Docs: https://developers.line.biz/en/reference/messaging-api/ # API Docs: https://developers.line.biz/en/reference/messaging-api/

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2021 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# PAHO MQTT Documentation: # PAHO MQTT Documentation:
# https://www.eclipse.org/paho/index.php?page=clients/python/docs/index.php # https://www.eclipse.org/paho/index.php?page=clients/python/docs/index.php
@ -317,7 +324,7 @@ class NotifyMQTT(NotifyBase):
ciphers=None) ciphers=None)
# Set our TLS Verify Flag # Set our TLS Verify Flag
self.client.tls_insecure_set(self.verify_certificate) self.client.tls_insecure_set(not self.verify_certificate)
# Establish our connection # Establish our connection
if self.client.connect( if self.client.connect(

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Create an account https://msg91.com/ if you don't already have one # Create an account https://msg91.com/ if you don't already have one
# #

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2020 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# To use this plugin, you need to create a webhook; you can read more about # To use this plugin, you need to create a webhook; you can read more about
# this here: # this here:

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2020 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import print_function from __future__ import print_function

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Signup @ https://www.mailgun.com/ # Signup @ https://www.mailgun.com/
# #

View file

@ -1,27 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# BSD 3-Clause License
# #
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com> # Apprise - Push Notification Library.
# All rights reserved. # Copyright (c) 2023, Chris Caron <lead2gold@gmail.com>
# #
# This code is licensed under the MIT License. # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # 1. Redistributions of source code must retain the above copyright notice,
# of this software and associated documentation files(the "Software"), to deal # this list of conditions and the following disclaimer.
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
# #
# The above copyright notice and this permission notice shall be included in # 2. Redistributions in binary form must reproduce the above copyright notice,
# all copies or substantial portions of the Software. # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 3. Neither the name of the copyright holder nor the names of its
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # contributors may be used to endorse or promote products derived from
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE # this software without specific prior written permission.
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# THE SOFTWARE. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import re import re
import requests import requests
@ -246,7 +253,7 @@ class NotifyMastodon(NotifyBase):
self.token = validate_regex(token) self.token = validate_regex(token)
if not self.token: if not self.token:
msg = 'An invalid Twitter Consumer Key was specified.' msg = 'An invalid Mastodon Access Token was specified.'
self.logger.warning(msg) self.logger.warning(msg)
raise TypeError(msg) raise TypeError(msg)

Some files were not shown because too many files have changed in this diff Show more