4.3. Howdy Core API
This document describes the lower level Plex core API, upon which all the command line and GUI tools are based. It lives in howdy.core.
4.3.1. howdy.core module
This module implements the lower-level functionality that does or has the following:
access and retrieve configuration and other data from an SQLite3 database using SQLAlchemy object relational mapping (ORM) classes. The SQLite3 database is stored in
~/.config/howdy/app.db.PlexConfigis an ORM class that stores configuration information.PlexGuestEmailMappingis an ORM class that stores all the email addresses that will receive Howdy email notifications.LastNewsletterDateis an ORM class that store one member (or row) – thedatetimeof when the Howdy newsletter was last updated.create_allinstantiates necessary SQLite3 tables in the configuration table if they don’t already exist.low level PyQt5 derived widgets used for the other GUIs in Howdy:
ProgressDialog,QDialogWithPrinting, andQLabelWithSave.initialization, in order to check for necessary prerequisites (see Prerequisites) and to install missing Python modules and packages (see Installation). This initialization is handled via a
HowdyInitializationsingleton object.
- class howdy.core.HtmlView(parent, htmlString='')
A convenient PyQt5 widget that displays rich and interactive HTML (HTML with CSS and Javascript). This extends
QWebEngineView.
- class howdy.core.LastNewsletterDate(**kwargs)
This SQLAlchemy ORM class contains the date at which the last newsletter was sent. It is not used much, and now that Tautulli has newsletter functionality, I very likely won’t use this at all. Stored into the
lastnewsletterdatetable in the SQLite3 configuration database.
- class howdy.core.PlexConfig(**kwargs)
This SQLAlchemy ORM class contains the configuration data used for running all the Howdy tools. Stored into the
plexconfigtable in the SQLite3 configuration database.- Variables:
service – the name of the configuration service we store. Index on this unique key. This is a
Columncontaining aStringof size 65536.data –
the JSON formatted information on the data stored here. For instance, username and password can be stored in the following way
{ 'username' : USERNAME, 'password' : PASSWORD }
- class howdy.core.PlexExcludedTrackerStubs(**kwargs)
This SQLAlchemy ORM class contains all the excluded trackers (as of 7 AUGUST 2022 I am looking at
stealth.si) when reconstructing magnet links. Stored in theplexexcludedtrackerstubstable in the SQlite3 configuration database.- Variables:
trackerstub – the torrent tracker stub to exclude. This is a
Columncontaining aStringobject of size 65536.
- class howdy.core.PlexGuestEmailMapping(**kwargs)
This SQLAlchemy ORM class contains mapping of emails of Plex server users, to other email addresses. This is used to determine other email addresses to which Howdy one-off or newsletter emails are delivered. Stored in the
plexguestemailmappingtable in the SQLite3 configuration database. The structure of each row in this table is straightforward. Each column in the table is a member of the object in this ORM class.- Variables:
plexemail – this is the main column, which must be the email of a Plex user who has access to the Plex server. This is a
Columncontaining aString.plexmapping – this is a collection of different email addresses, to which the emails are sent. For example, if a Plex user with email address
A@email.comwould like to send email toB@mail.comandC@mail.com, the plexmapping column would beB@mail.com,C@mail.com. NONE of the mapped emails will match email. This is aColumncontaining aStringof size 65536.plexreplaceexisting – this is a boolean that determines whether email also goes to the Plex user’s email address. From the example above, if
Truethen a Plex user atA@mail.comwill have email delivered ONLY toB@mail.comandC@mail.com. IfFalse, then that same Plex user will have email delivered to all three email addresses (A@mail.com,B@mail.com, andC@mail.com). This is aColumncontaining aBoolean.
- class howdy.core.ProgressDialog(parent, windowTitle='', doQuit=True)
A convenient PyQt5 widget, inheriting from
QDialogWithPrinting, that acts as a GUI blocking progress window for longer lasting operations. Like its parent class, this dialog widget is also resizable. This shows the passage of the underlying slow process in 5 second increments.This progress dialog exposes three methods –
addText,stopDialog, andstartDialog– to which a customQThreadobject can connect.startDialogis triggered on long operation start, sometimes with an initial message.addTextis triggered when some intermediate progress text must be returned.stopDialogis triggered on process end.
- Parameters:
parent (
QWidget) – the parentQWidgeton which this dialog widget blocks.windowTitle (str) – the label to put on this progress dialog in an internal
QLabel.doQuit (bool) – if
True, then using the quit shortcuts (EscorCtrl+Shift+Q) will cause the underlying program to exit. Otherwise, hide the progress dialog.
- Variables:
mainDialog (
QTextEdit) – the main dialog widget in this GUI.parsedHTML (
BeautifulSoup) – theBeautifulSoupstructure that contains the indexable tree of progress dialogs.elapsedTime (
QLabel) – the bottomQLabelwidget that displays how much time (in seconds) has passed.timer (
QTimer) – theQTimersub-thread that listens every 5 seconds before emitting a signal.t0 (float) – the UNIX time, in seconds with resolution of microseconds.
- addText(text)
adds some text to this progress dialog window.
- Parameters:
text (str) – the text to add.
- showTime()
method connected to the internal
timerthat prints out how many seconds have passed, on the underlyingelapsedTimeQLabel.
- startDialog(initString='')
starts running the progress dialog, with an optional labeling string, and starts the timer.
- Parameters:
initString (str) – optional internal labeling string.
- stopDialog()
stops running, and hides, this progress dialog.
- class howdy.core.ProgressDialogThread(parent, title)
This subclassing of
QThreadprovides a convenient scaffolding to run, in a non-blocking fashion, some long-running processes with an asssociatedProgressDialogwidget.Subclasses of this object need to have a particular structure for their
__init__method. The first three arguments MUST beself,parent,selfis a reference to this object.parentis the parentQWidgetto which theProgressDialogattribute, namedprogress_dialog, is the child.titleis the title ofprogress_dialog. Here is an example, where an example class namedProgressDialogThreadChildClassinherits fromProgressDialogThread.def __init__( self, parent, *args, **kwargs ): super( ProgressDialogThreadChildClass, self ).__init__( parent, title ) # own code to initialize based on *args and **kwargs
This thing has an associated
runmethod that is expected to be partially implemented in the following manner for subclasses ofProgressDialogThread.It must start with
self.progress_dialog.show( )to show the progress dialog widget.It must end with this command,
self.stopDialog.emit( )to hide the progress dialog widget.
Here is an example.
def run( self ): self.progress_dialog.show( ) # run its own way self.stopDialog.emit( )
In the
runmethod, if one wants to print out something intoprogess_dialog, then there should be these types of commands inrun:self.emitString.emit( mystr ), wheremystris astrmessage to show inprogress_dialog, andemitStringis apyqtsignalconnected to theprogress_dialogobject’saddText( ).- Parameters:
- Variables:
emitString – the signal, with
strsignature, that is triggered to send progress messages intoprogress_dialog.stopDialog – the signal that is triggered to stop the
progress_dialog, callingstopDialog.startDialog – the signal, with
strsignature, that is triggered to restart theprogress_dialogwidget, callingstartDialog.progress_dialog – the GUI that shows, in a non-blocking fashion, the progress on some longer-running method.
time0 (int) – a convenience attribute, the UTC time at which the
progress_dialogobject was first instantiated. Can be used to determine the time each submethod takes (for example,time.time( ) - self.time0).
See also
- class howdy.core.QDialogWithPrinting(parent, isIsolated=True, doQuit=True)
A convenient PyQt5 widget, inheriting from
QDialog, that allows for screen grabs and keyboard shortcuts to either hide this dialog window or quit the underlying program. This PyQt5 widget is also resizable, in relative increments of 5% larger or smaller, to a maximum of \(1.05^5\) times the initial size, and to a minimum of \(1.05^{-5}\) times the initial size.- Parameters:
parent (
QWidget) – the parentQWidgetto this dialog widget.isIsolated (bool) – If
True, then this widget is detached from its parent. IfFalse, then this widget is embedded into a layout in the parent widget.doQuit (bool) – if
True, then using the quit shortcuts (EscorCtrl+Shift+Q) will cause the underlying program to exit. Otherwise, hide the progress dialog.
- Variables:
indexScalingSignal – a
pyqtSignalthat can be connected to other PyQt5 events or methods, if resize events want to be recorded.initWidth (int) – the initial width of the GUI in pixels.
initHeight (int) – the initial heigth of the GUI in pixels.
- makeBigger()
makes the widget incrementally 5% larger, for a maximum of \(1.05^5\), or approximately 28% larger than, the initial size.
- makeSmaller()
makes the widget incrementally 5% smaller, for a minimum of \(1.05^{-5}\), or approximately 28% smaller than, the initial size.
- resetSize()
reset the widget size to the initial size.
- reset_sizes()
Sets the default widget size to the current size.
- screenGrab()
take a screen shot of itself and saver to a PNG file through a
QFileDialogwidget.See also
- class howdy.core.QLabelWithSave(parent=None)
A convenient PyQt5 widget that inherits from
QLabel, but allows screen shots.- contextMenuEvent(event)
Constructs a context menu with a single action, Save Pixmap, that takes a screen shot of this widget, using
screenGrab.- Parameters:
event (QEvent) – default
QEventargument needed to create a context menu. Is not used in this reimplementation.
- screenGrab()
take a screen shot of itself and save to a PNG file through a
QFileDialogwidget.See also
- howdy.core.check_valid_RST(myString)
Checks to see whether the input string is valid reStructuredText.
- Parameters:
myString (str) – the candidate reStructuredText input.
- Returns:
Trueif valid, otherwiseFalse.- Return type:
See also
- howdy.core.convert_string_RST(myString)
Converts a valid reStructuredText input string into rich HTML.
- Parameters:
myString (str) – the candidate reStructuredText input.
- Returns:
If the input string is valid reStructuredText, returns the rich HTML as a
string. Otherwise emits alogging error messageand returnsNone.- Return type:
See also
- howdy.core.create_all()
creates the necessary SQLite3 tables into the database file
~/.config/howdy/app.dbif they don’t already exist, but only if not building documentation in Read the docs.
- howdy.core.geoip_reader = <geoip2.database.Reader object>
This contains an on-disk MaxMind database, of type
geoip2.database.Reader, containing location information for IP addresses.
- howdy.core.get_formatted_duration(totdur)
This routine spits out a nice, formatted string representation of the duration, which is of type
datetime.
- howdy.core.get_formatted_size(totsizebytes)
This routine spits out a nice, formatted string representation of a file size, which is represented in int.
This method works like this.
get_formatted_size( int(2e3) ) = '1.953 kB' # kilobytes get_formatted_size( int(2e6) ) = '1.907 MB' # megabytes get_formatted_size( int(2e9) ) = '1.863 GB' # gigabytes
- Parameters:
totsizebytes (int) – size of a file in bytes.
- Returns:
Formatted representation of that file size.
- Return type:
See also
- howdy.core.get_formatted_size_MB(totsizeMB)
Same as
get_formatted_size, except this operates on file sizes in units of megabytes rather than bytes.- Parameters:
totsizeMB (int) – size of the file in megabytes.
- Returns:
Formatted representation of that file size.
- Return type:
See also
- howdy.core.get_lastupdated_string(dt=datetime.datetime(2025, 11, 14, 1, 12, 50, 668186))
Returns a string representation of a
datetimeobject.- Parameters:
dt – the date and time, of type
datetime.- Returns:
a
strwith this format,Saturday, 28 September 2019, at 3:41 AM.- Return type:
See also
- howdy.core.get_maximum_matchval(check_string, input_string)
Returns the Levenshtein distance of two strings, implemented using A perfect match is a score of
100.0.- Parameters:
- Returns:
the Levenshtein distance between the two strings.
- Return type:
- howdy.core.get_popularity_color(hpop, alpha=1.0)
Get a color that represents some darkish cool looking color interpolated between 0 and 1.
- howdy.core.returnQAppWithFonts()
returns a customized
QApplicationwith all custom fonts loaded.
- howdy.core.splitall(path_init)
This routine is used by
get_path_data_on_tvshowto split a TV show file path into separate directory delimited tokens.
4.3.2. howdy.core.core module
This module implements the functionality to do the following:
access your Plex server, and determine those Plex servers to which you have access.
retrieve and summarize data in the Plex libraries.
miscellaneous functionalities, such as the following: getting formatted date strings from a
dateobject.
- howdy.core.core.add_mapping(plex_email, plex_emails, new_emails, replace_existing)
Changes the mapping of one member of the Plex server’s emails from an old set of emails to a new set of emails. The command line tool, howdy_core_cli, is a front end to the lower-level functionality implemented here.
- howdy.core.core.checkServerCredentials(doLocal=False, verify=True, checkWorkingServer=False)
Returns get a local or remote URL and Plex access token to allow for API access to the server. If there is already a VALID token in the SQLite3 configuration database, then uses that. Otherwise, tries to acquire a Plex access token.
- Parameters:
doLocal (bool) – optional argument, whether to get a local (
http://localhost:32400) or remote URL. Default isFalse(look for the remote URL).verify (bool) – optional argument, whether to verify SSL connections. Default is
True.checkWorkingServer (bool) – optional argument, whether to check if the server is working. Default is
True.
- Returns:
a tuple of server URL and Plex access token.
- Return type:
See also
- howdy.core.core.check_imgurl_credentials(clientID, clientSECRET, clientREFRESHTOKEN, verify=True)
validate the Imgur API credentials with the provided API client ID, secret, and refresh token.
- Parameters:
- Returns:
whether the new credentials are correct.
- Return type:
See also
- howdy.core.core.check_jackett_credentials(url, apikey, verify=True)
validate the Jackett server credentials with the provided URL and API key.
- Parameters:
- Returns:
a
tuple. If successful, this is a tuple of the server’s URL and the string"SUCCESS". If unsuccessful, this is a tuple ofNoneTypeand error message string.- Return type:
See also
- howdy.core.core.fill_out_movies_stuff(token, fullURL='http://localhost:32400', verify=True)
Creates a
tuple. The first element of thetupleis alistof movies from this Plex server. Each element in that list is adictwith the following structure with 12 keys and values, as shown in this example{ 'title': 'Blue Collar', 'rating': 10.0, 'contentrating': 'R', 'picurl': 'https://24.5.231.186:32400/library/metadata/46001/art/1569656413', 'releasedate': datetime.date(1978, 2, 10), 'addedat': datetime.date(2019, 6, 6), 'summary': "Fed up with mistreatment at the hands of both management and union brass, and coupled with financial hardships on each man's end, three auto assembly line workers hatch a plan to rob a safe at union headquarters.", 'duration': 6820.394, 'totsize': 935506414.0, 'localpic': True, 'imdb_id': 'tt0077248', 'genre': 'drama' }
The second element of the
tupleis alistof movie genres on the Plex server.
- howdy.core.core.getCredentials(verify=True, checkWorkingServer=True)
Returns the Plex user account information stored in
~/.config/howdy/app.db.- Parameters:
- Returns:
the Plex account tuple of
(username, password).- Return type:
See also
- howdy.core.core.getTokenForUsernamePassword(username, password, verify=True)
get the Plex access token for the Plex server given an username and password for the user account.
- Parameters:
- Returns:
the Plex access token.
- Return type:
See also
- howdy.core.core.get_all_servers(token, verify=True)
Find all the Plex servers for which you have access.
- Parameters:
- Returns:
a dictionary of servers accessible to you. Each key is the Plex server’s name, and the value is a
dictthat looks like this.
{ 'owned' : OWNED, # boolean on whether server owned by you 'access token' : TOKEN, # string access token to server 'url' : URL # remote URL of the form https://IP-ADDRESS:PORT }
- Return type:
See also
- howdy.core.core.get_cloudconvert_credentials()
retrieves the CloudConvert API V2 credentials from the SQLite3 configuration database.
- Returns:
a
dictof the CloudConvert API V2 credentials. Its structure is,
{ 'clientID': XXXX, 'clientSECRET': XXXX }
- Return type:
See also
- howdy.core.core.get_current_date_newsletter()
the last date and time at which the Howdy email newsletter was updated.
- Returns:
the date and time of the most recent previous email newsletter.
- Return type:
See also
- howdy.core.core.get_date_from_datestring(dstring)
Returns a
dateobject from a date string with the format, “January 1, 2000”.
- howdy.core.core.get_email_contacts(token, fullURL='https://localhost:32400', verify=True)
list of all email addresses of friends who have stream access to your Plex server.
- howdy.core.core.get_imgurl_credentials()
retrieves the Imgur API credentials from the SQLite3 configuration database.
{ 'clientID': XXXX, 'clientSECRET': XXXX, 'clientREFRESHTOKEN': XXXX, 'mainALBUMID': XXXX, 'mainALBUMTITLE': XXXX }
- Return type:
See also
- howdy.core.core.get_jackett_credentials()
retrieves the Jackett server’s API credentials from the SQLite3 configuration database.
- howdy.core.core.get_lastN_movies(lastN, token, fullURL='http://localhost:32400', useLastNewsletterDate=True)
Returns the last \(N\) movies that were uploaded to the Plex server, either after the last date at which a newsletter was sent out or not.
- Parameters:
- Returns:
a
listof Plex movies. Each element in the list istupleof the movie: title, year,datetime, and The Movie Database <TMDB_> URL of the movie.- Return type:
dict.
- howdy.core.core.get_libraries(token, fullURL='http://localhost:32400', do_full=False, timeout=None)
Gets the
dictof libraries on the Plex server. The key is the library number, while the value can be either the name of the library or atupleof library name and library type
- howdy.core.core.get_library_data(title, token, fullURL='http://localhost:32400', num_threads=16, timeout=None, mainPath=None)
Returns the data on the specific Plex library, as a
dict. This lower level functionality lives in the same space as PlexAPI. Three types of library data can be returned: movies, TV shows, and music.Movie data has this JSON like structure.
moviedatais an example movie data dictionary.moviedatais adictwhose keys (of typestr) are the main movie genres in the Plex library, such ascomedy.Each value in
moviedata[<genre>]is alistof movies of that (main) genre.Each
movieinmoviedata[<genre>]is adictwith the following ten keys and values.title:strmovie’s name.rating:floatthe movie’s quality rating as a number between0.0and10.0.contentrating:strthe MPAA content rating for the movie (such asPG,PG-13,R, orNR).releasedate:dateof when the movie was first released.addedat:dateof when the movie was added to the Plex server.summary:strplot summary of the movie.duration:floatmovie’s duration in seconds.totsize:intsize of the movie file in bytes.localpic:boolcurrently unused variable, alwaysTrue.
An example
moviedatadictwith one genre (comedy) and ten highly rated movies can be found inmoviedata examplein JSON format.
TV data has this JSON like structure.
tvdatais an example TV data dictionary.tvdatais adictwhose keys are the individual TV shows.Each value in
tvdata[<showname>]is a dictionary with four keys:title(strname of the show, <showname>),summary(strdescription of the show),picturl(strURL of the poster for the show), andseasons(dictwhose keys are the seasons of the show).tvdata[<showname>]['seasons']is adictwhose keys are the seasons. If the show has specials, then those episodes are in season 0.this
dicthas two keys:seasonpicurl(strURL of the poster for the season), andepisodes(dictof the episodes for that season).tvdata[<showname>]['seasons']['episodes']is adictwhose keys are the episode numbers, and whose value is adictwith the following nine keys and values.title:strtitle of the episode.episodepicurl:strURL of the poster of the episode.date aired:dateof when the episode first aired.summary:strsummary of the episode’s plot.duration::floatepisode duration in seconds.size:intsize of the episode file in bytes.director:listof the episode’s directors.writer:listof the episode’s writers.
An example
tvdatadictwith one finished HBO show, The Brink, can be found intvdata examplein JSON format.
Music data has this JSON like structure.
musicdatais an example music data dictionary.musicdatais adictwhose keys are the individual artists or groups (such as The Beatles).Each value in
musicdata[<artistname>]is adictof albums associated with<artistname>on the Plex server.The key is the album name, and the value is another
dictwith three keys.musicdata[<artistname>][<albumname>]['tracks']is alistofdicts representing each song that is on the Plex server. Each songdicthas the following keys and values.An example
musicdatadictwith one artist, The Beatles, can be found inmusicdata example. Sincedateis not JSON-serializable, I have represented eachcurdateas a string in this format: DAY MONTH YEAR (such as13 January 2020).
- Parameters:
title (str) – the name of the library.
num_threads (int) – the number of concurrent threads used to access the Plex server and get the library data.
timeout (int) – optional time, in seconds, to wait for an HTTP conection to the Plex server.
mainPath (str) – optional prefix directory to put in front of all the file paths on the Plex server.
- Returns:
- Return type:
- howdy.core.core.get_library_stats(key, token, fullURL='http://localhost:32400', sinceDate=None)
Gets summary data on a specific library on the Plex server. returned as a
dict. The Plex librarymediatypecan be one ofmovie(Movies),show(TV shows), orartist(Music). The common part of thedictlooks like the following.{ 'fullURL' : FULLURL, # URL of the Plex server in the form of https://IP-ADDRESS:PORT 'title' : TITLE, # name of the Plex library 'mediatype' : MEDIATYPE, # one of "movie", "show", or "artist" }
Here are what the extra parts of this dictionary look like.
If the library is a
movie(Movies), then{ 'num_movies' : num_movies, # total number of movies in this library. 'totdur' : totdur, # total duration in seconds of all movies. 'totsize' : totsize, # total size in bytes of all movies. 'genres' : sorted_by_genre # another dictionary subdivided by, showing # movies, size, and duration by genre. }
sorted_by_genreis also adict, whose keys are the separate movie genres in this Plex library (such asaction,horror,comedy). Each value in this dictionary is another dictionary that looks like this.{ 'num_movies' : num_movies_gen, # total number of movies in this genre. 'totdur' : totdur_gen, # total duration in seconds of movies in this genre. 'totsize' : totsize_gen, # total size in bytes of movies in this genre. }
If the library is a
show(TV Shows), then{ 'num_tveps' : num_tveps, # total number of TV episodes in this library. 'num_tvshows' : num_tvshows, # total number of TV shows in this library. 'totdur' : totdur, # total duration in seconds of all TV shows. 'totsize' : totsize # otal size in bytes of all TV shows. }
If the library is an
artist(Music), then{ 'num_songs' : num_songs, # total number of songs in this library. 'num_albums' : num_albums, # total number of albums in this library. 'num_artists' : num_artists, # total number of unique artists in this library. 'totdur' : totdur, # total duration in seconds of all songs. 'totsize' : totsize # total size in bytes of all songs. }
- Parameters:
- Returns:
- Return type:
See also
- howdy.core.core.get_mapped_email_contacts(token, fullURL='https://localhost:32400', verify=True)
list of all email addresses (including Plex server friends and mapped emails) to send Howdy related emails.
- howdy.core.core.get_movies_libraries(token, fullURL='http://localhost:32400')
Returns a
listof the key numbers of all Plex movie libraries on the Plex server.
- howdy.core.core.get_pic_data(plexPICURL, token=None)
Get the PNG data as a
Responseobject, from a movie picture URL on the Plex server.
- howdy.core.core.get_updated_at(token, fullURL='https://localhost:32400')
Get the date and time at which the Plex server was last updated, as a
datetimeobject.
- howdy.core.core.oauthCheckGoogleCredentials(bypass=False)
Checks whether the Google OAuth2 authentication settings exist in the SQLite3 configuration database. The format of the authentication data in the configuration database is,
{ 'access_token': XXXX, 'client_id': YYYY, 'client_secret': ZZZZ, 'refresh_token': AAAA, 'token_expiry': BBBB, 'token_uri': 'https://accounts.google.com/o/oauth2/token', 'user_agent': None, 'revoke_uri': 'https://oauth2.googleapis.com/revoke', 'id_token': None, 'id_token_jwt': None, 'token_response': { 'access_token': XXXX, 'expires_in': 3600, 'refresh_token': AAAA, 'scope': 'https://www.googleapis.com/auth/gmail.send https://www.googleapis.com/auth/contacts.readonly https://www.googleapis.com/auth/youtube.readonly https://www.googleapis.com/auth/musicmanager https://www.googleapis.com/auth/spreadsheets', 'token_type': 'Bearer' }, 'scopes': ['https://www.googleapis.com/auth/gmail.send', 'https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/youtube.readonly', 'https://www.googleapis.com/auth/contacts.readonly', 'https://www.googleapis.com/auth/musicmanager'], 'token_info_uri': 'https://oauth2.googleapis.com/tokeninfo', 'invalid': False, '_class': 'OAuth2Credentials', '_module': 'oauth2client.client' }
If
datais this dictionary, note the scopes defined in thedata['scopes']anddata['token_response']['scope'].- Parameters:
bypass (bool) – if
True, then ignore what exists in the database under google crdentials.- Returns:
a
tupleof status and message. If the settings are in the database, returns( True, 'SUCCESS' ). If they are not, returns( False, 'GOOGLE AUTHENTICATION CREDENTIALS DO NOT EXIST.' ).- Return type:
tuple.
- howdy.core.core.oauthGetGoogleCredentials(verify=True)
Gets the Google Oauth2 credentials, stored in the SQLite3 configuration database, in the form of a refreshed
Credentialsobject. This OAuth2 authentication method is used for ALL the services accessed by Howdy.- Parameters:
verify (bool) – optional argument, whether to verify SSL connections. Default is
True.- Returns:
a
Credentialsform of the Google Oauth2 credentials for various Oauth2 services.- Return type:
- howdy.core.core.oauthGetOauth2ClientGoogleCredentials()
Gets the Google Oauth2 credentials, stored in the SQLite3 configuration database, in the form of a refreshed
AccessTokenCredentialsobject. This OAuth2 authentication method IS used for all the services accessed by Howdy.- Returns:
a
AccessTokenCredentialsform of the Google Oauth2 credentials for various Oauth2 services.- Return type:
- howdy.core.core.oauth_generate_google_permission_url()
Generates a Google OAuth2 web-based flow for all the Google services used in Howdy. The authentication process that uses this flow is described in this subsection. Here are the programmatic steps to finally generate an
AccessTokenCredentialsobject.Get the
OAuth2WebServerFlowand authentication URI.flow, auth_uri = oauth_generate_google_permission_url( )
Go to the URL,
auth_uri, in a browser, grant permissions, and copy the authorization code in the browser window. This authorization code is referred to asauthorization_code.Create the
AccessTokenCredentialsusingauthorization_code.credentials = flow.step2_exchange( authorization_code )
- Returns:
a
tupleof two elements. The first element is anOAuth2WebServerFlowweb server flow object. The second element is the redirection URIstringthat redirects the user to begin the authorization flow.- Return type:
- howdy.core.core.oauth_store_google_credentials(credentials)
Store the Google OAuth2 credentials, in the form of a
AccessTokenCredentialsobject, into the SQLite3 configuration database.- Parameters:
credentials – the
AccessTokenCredentialsobject to store into the database.
- howdy.core.core.processValidHTMLWithPNG(html, pngDataDict, doEmbed=False)
Returns a prettified HTML document, using BeautifulSoup, including all PNG image data (whether URLs or Base 64 encoded data) in
<img>tags.- Parameters:
html (str) – the initial HTML document into which images are to be embedded.
pngDataDict (dict) – dictionary of PNG data. Key is the name of the PNG file (must end in .png). Value is a tuple of type
(b64data, widthInCM, url).b64datais the Base 64 encoded binary representation of the PNG image.widthInCmis the image width in cm.urlis the URL address of the image.doEmbed (bool) – If
True, then the image source tag uses the Base 64 encoded data. IfFalse, the image source tag is the URL.
- Returns:
prettified HTML document with the images located in it.
- Return type:
- howdy.core.core.pushCredentials(username, password)
replace the Plex server credentials, located in
~/.config/howdy/app.db, with a newusernameandpassword.- Parameters:
- Returns:
if successful, return a string,
SUCCESS. If unsuccessful, returns a string reason of why it failed.- Return type:
See also
- howdy.core.core.refresh_library(key, library_dict, token, fullURL='http://localhost:32400')
Lower level front-end to
plex_resynclibs.pythat refreshes a Plex server library. Here I use instructions found in this Plex forum article on URL commands.
- howdy.core.core.rstToHTML(rstString)
Converts a reStructuredText string into HTML, then prettifies the intermediate HTML using BeautifulSoup.
- Parameters:
rstString (str) – the initial restructuredText string.
- Returns:
the final prettified, formatted HTML
string.- Return type:
- howdy.core.core.store_cloudconvert_credentials(clientID, clientTOKEN)
stores the CloudConvert API V2 credentials into the SQLite3 configuration database.
- Parameters:
clientID (str) – the CloudConvert API V2 client ID. This is the name on the CloudConvert dashboard’s API V2 key name. For example, for myself it is named
TanimIslamCloudConvert.clientTOKEN (str) – the CloudConvert API V2 client token.
- Returns:
the string
"SUCCESS"if could store the new CloudConvert credentials. Otherwise, the string'ERROR, COULD NOT STORE CLOUDCONVERT API V2 CREDENTIALS.'.- Return type:
See also
- howdy.core.core.store_imgurl_credentials(clientID, clientSECRET, clientREFRESHTOKEN, verify=True, mainALBUMID=None, mainALBUMNAME=None)
stores the Imgur API credentials into the SQLite3 configuration database.
- Parameters:
- Returns:
the string
"SUCCESS"if could store the new Imgur credentials. Otherwise, the string'ERROR, COULD NOT STORE IMGURL CREDENTIALS.'.- Return type:
See also
- howdy.core.core.store_jackett_credentials(url, apikey, verify=True)
stores the Jackett server’s API credentials into the SQLite3 configuration database.
- Parameters:
- Returns:
the string
"SUCCESS"if could store the new Jackett server credentials. Otherwise, some illuminating error message.- Return type:
See also
4.3.3. howdy.core.core_deluge module
This module implements the functionality to interact with a Seedhost seedbox Deluge torrent server, by copying a minimal set of the functionality of a Deluge torrent client. The data formatting in this module is largely or wholly copied from the Deluge SDK. The much reduced Deluge torrent client, howdy_deluge_console, is a CLI front-end to this module.
- howdy.core.core_deluge.create_deluge_client(url, port, username, password)
Creates a minimal Deluge torrent client to the Deluge seedbox server.
- Parameters:
- Returns:
previously a lightweight Deluge RPC client, although now it is a
DelugeRPCClient.
- howdy.core.core_deluge.deluge_add_magnet_file(client, magnet_uri)
Uploads a Magnet URI to the Deluge server through the Deluge RPC client.
- Parameters:
client – the Deluge RPC client.
magnet_uri (str) – the Magnet URI to upload.
- Returns:
if successful, returns the MD5 hash of the uploaded torrent as a
str. If unsuccessful, returnsNone.
- howdy.core.core_deluge.deluge_add_torrent_file(client, torrent_file_name)
Higher level method that takes a torrent file on disk and uploads to the Deluge server through the Deluge RPC client.
- Parameters:
client – the Deluge RPC client.
torrent_file_name (str) – name of the candidate file.
- Returns:
if successful, returns the MD5 hash of the uploaded torrent as a
str. If unsuccessful, returnsNone.
See also
- howdy.core.core_deluge.deluge_add_torrent_file_as_data(client, torrent_file_name, torrent_file_data)
Higher level method that takes a torrent file name, and its byte data representation, and uploads to the Deluge server through the Deluge RPC client.
- Parameters:
client – the Deluge RPC client.
torrent_file_name (str) – name of the candidate file.
torrent_file_data (bytes) – byte representation of the torrent file data.
- Returns:
if successful, returns the MD5 hash of the uploaded torrent as a
str. If unsuccessful, returnsNone.
See also
- howdy.core.core_deluge.deluge_add_url(client, torrent_url)
Adds a torrent file via URL to the Deluge server through the Deluge RPC client. If the URL is valid, then added. If the URL is invalid, then nothing happens.
- Parameters:
client – the Deluge RPC client.
torrent_url (str) – candidate URL.
- howdy.core.core_deluge.deluge_get_matching_torrents(client, torrent_id_strings)
Given a
listof possibly truncated MD5 hashes of candidate torrents on the Deluge server, returns alistof MD5 sums of torrents that match what was provided.- Parameters:
client – the Deluge RPC client.
torrent_id_strings – the candidate
listof truncated MD5 hashes on the Deluge server. The[ '*' ]input means to look for all torrents on the Deluge server.
- Returns:
a
listof candidate torrents, as their MD5 hash, tat matchtorrent_id_strings. Iftorrent_id_strings == ['*'], then return all the torrents (as MD5 hashes) on the Deluge server.- Return type:
- howdy.core.core_deluge.deluge_get_torrents_info(client)
Returns a
dictof status info for every torrent on the Deluge server through the Deluge RPC client. The key in thisdictis the MD5 hash of the torrent, and its value is a statusdict. For each torrent, here are the keys in the statusdict:active_time,all_time_download,distributed_copies,download_location,download_payload_rate,eta,file_priorities,file_progress,files,is_finished,is_seed,last_seen_complete,name,next_announce,num_peers,num_pieces,num_seeds,peers,piece_length,progress,ratio,seed_rank,seeding_time,state,time_added,time_since_transfer,total_done,total_payload_download,total_payload_upload,total_peers,total_seeds,total_size,total_uploaded,tracker_host,tracker_status,upload_payload_rate.- Parameters:
client – the Deluge RPC client.
- Returns:
a
dictof statusdictfor each torrent on the Deluge server.- Return type:
- howdy.core.core_deluge.deluge_pause_torrent(client, torrent_ids)
Pauses torrents on the Deluge server. Unlike other methods here, this does not use the Deluge RPC client lower-level RPC calls, but system command line calls to the deluge-console client. If the deluge-console executable cannot be found, then this does nothing. I do not know the Deluge RPC client is not working.
- Parameters:
client – the Deluge RPC client. In this case, only the configuration info (username, password, URL, and port) are used.
torrent_ids –
listof MD5 hashes on the Deluge server.
- howdy.core.core_deluge.deluge_remove_torrent(client, torrent_ids, remove_data=False)
Remove torrents from the Deluge server through the Deluge RPC client.
- Parameters:
client – the Deluge RPC client.
torrent_ids –
listof MD5 hashes on the Deluge server.remove_data (bool) – if
True, remove the torrent and delete all data associated with the torrent on disk. IfFalse, just remove the torrent.
- howdy.core.core_deluge.deluge_resume_torrent(client, torrent_ids)
Resumes torrents on the Deluge server. Unlike other methods here, this does not use the Deluge RPC client lower-level RPC calls, but system command line calls to the deluge-console client. If the deluge-console executable cannot be found, then this does nothing. I do not know the Deluge RPC client is not working.
- Parameters:
client – the Deluge RPC client. In this case, only the configuration info (username, password, URL, and port) are used.
torrent_ids –
listof MD5 hashes on the Deluge server.
- howdy.core.core_deluge.get_deluge_client()
Using a minimal Deluge torrent client from server credentials stored in the SQLite3 configuration database.
- Returns:
a
tuple. If successful, the first element is a lightweight Deluge RPC client and the second element is the string'SUCCESS'. If unsuccessful, the first element isNoneand the second element is an error string.- Return type:
- howdy.core.core_deluge.get_deluge_credentials()
Gets the Deluge server credentials from the SQLite3 configuration database. The data looks like this.
{ 'url': XXXX, 'port': YYYY, 'username': AAAA, 'password': BBBB }
- Returns:
dictionary of Deluge server settings.
- Return type:
- howdy.core.core_deluge.push_deluge_credentials(url, port, username, password)
Stores the Deluge server credentials into the SQLite3 configuration database.
- Parameters:
- Returns:
if successful (due to correct Deluge server settings), returns
'SUCCESS'. If unsuccessful, returns'ERROR, INVALID SETTINGS FOR DELUGE CLIENT.'- Return type:
4.3.4. howdy.core.core_transmission module
This module implements the functionality to interact with a Seedhost seedbox Transmission torrent server. The custom Transmission torrent client, howdy_transmission_console, is a CLI front-end to this module, which uses the lower level transmission_rpc module functionality.
- howdy.core.core_transmission.create_transmission_client(url, username, password)
Creates a minimal Transmission torrent client to the Transmission seedbox server.
- Parameters:
url (str) – URL of the Transmission server.
username (str) – server account username.
password (str) – server account password.
- Returns:
the seedbox server’s Transmission RPC client.
- Return type:
- howdy.core.core_transmission.get_transmission_client()
Returns a minimal Transmission torrent client from server credentials stored in the SQLite3 configuration database.
- Returns:
a
tuple. If successful, the first element is a lightweightTransmissionRPCClient, and the second element is the string'SUCCESS'. If unsuccessful, the first element isNoneand the second element is an error string.- Return type:
- howdy.core.core_transmission.get_transmission_credentials()
Gets the Transmission server credentials from the SQLite3 configuration database. The data looks like this.
{ 'url': XXXX, 'username': AAAA, 'password': BBBB }
- Returns:
dictionary of Transmission server settings.
- Return type:
- howdy.core.core_transmission.push_transmission_credentials(url, username, password)
Stores the Transmission server credentials into the SQLite3 configuration database.
- Parameters:
url (str) – URL of the Transmission server.
username (str) – server account username.
password (str) – server account password.
- Returns:
if successful (due to correct Transmission server settings), returns
'SUCCESS'. If unsuccessful, returns'ERROR, INVALID SETTINGS FOR TRANSMISSION CLIENT.'- Return type:
- howdy.core.core_transmission.transmission_add_magnet_file(client, magnet_uri)
Uploads a Magnet URI to the Transmission server through the
TransmissionRPCClient.- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.magnet_uri (str) – the Magnet URI to upload.
- Returns:
if successful, returns the MD5 hash of the uploaded torrent as a
str. If unsuccessful, returnsNone.
- howdy.core.core_transmission.transmission_add_torrent_file(client, torrent_file_name)
Higher level method that takes a torrent file on disk and uploads to the Transmission server through the
TransmissionRPCClient.- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.torrent_file_name (str) – name of the candidate file.
- Returns:
if successful, returns the MD5 hash of the uploaded torrent as a
str. If unsuccessful, returnsNone.
See also
- howdy.core.core_transmission.transmission_add_torrent_file_as_data(client, torrent_file_data)
Higher level method that takes a torrent file name, and its byte data representation, and uploads to the Transmission server through the
TransmissionRPCClient.- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.torrent_file_data (bytes) – byte representation of the torrent file data.
- Returns:
if successful, returns the MD5 hash of the uploaded torrent as a
str. If unsuccessful, returnsNone.
See also
- howdy.core.core_transmission.transmission_add_url(client, torrent_url)
Adds a torrent file via URL to the Transmission server through the
TransmissionRPCClient. If the URL is valid, then added. If the URL is invalid, then nothing happens.- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.torrent_url (str) – candidate URL.
- howdy.core.core_transmission.transmission_get_matching_torrents(client, torrent_id_strings)
Given a
listof possibly truncated MD5 hashes of candidate torrents on the Transmission server, returns alistof MD5 sums of torrents that match what was provided.- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.torrent_id_strings (list) – the candidate
listof truncated MD5 hashes on the Transmission server. The[ '*' ]input means to look for all torrents on the Transmission server.
- Returns:
a
listof candidate torrents, as their MD5 hash, tat matchtorrent_id_strings. Iftorrent_id_strings == ['*'], then return all the torrents (as MD5 hashes) on the Transmission server.- Return type:
- howdy.core.core_transmission.transmission_get_torrents_info(client)
Returns a
dictof status info for every torrent on the Transmission server through theTransmissionRPCClient.The key in this
dictis the MD5 hash of the torrent, and its value is a statusdict.For each torrent, here are the keys in the status
dict:name,state,download rate,upload rate,eta(which may beNoneif download has not started),num seeds,total seeds,num peers,total peers,availability,total done,total size,ratio,seed time,active time,tracker status, andprogress.- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.- Returns:
a
dictof statusdictfor each torrent on the Transmission server.- Return type:
- howdy.core.core_transmission.transmission_pause_torrent(client, torrent_ids)
Pauses torrents on the Transmission server.
- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.torrent_ids (list) –
listof MD5 hashes on the Transmission server.
- howdy.core.core_transmission.transmission_remove_torrent(client, torrent_ids, remove_data=False)
Remove torrents from the Transmission server through the
TransmissionRPCClient.- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.torrent_ids (list) –
listof MD5 hashes on the Transmission server.remove_data (bool) – if
True, remove the torrent and delete all data associated with the torrent on disk. IfFalse, just remove the torrent.
- howdy.core.core_transmission.transmission_resume_torrent(client, torrent_ids)
Resumes torrents on the Transmission server.
- Parameters:
client (
TransmissionRPCClient) – the Transmission RPC client.torrent_ids (list) –
listof MD5 hashes on the Transmission server.
4.3.5. howdy.core.core_rsync module
This module implements the functionality to interact with a Seedhost seedbox SSH server to download or upload files and directories using the rsync protocol tunneled through SSH. rsync_subproc is a CLI front-end to this module.
- howdy.core.core_rsync.check_credentials(local_dir, sshpath, password, subdir=None)
Checks whether one can download to (or upload from) the directory
local_diron the Plex server to the remote SSH server.- Parameters:
local_dir (str) – the local directory, on the Plex server, into which to download files from the remote SSH server.
sshpath (str) – the full path with username and host name for the SSH server. Format is
'username@hostname'.password (str) – the password to connect as the SSH server.
subdir (str) – if not
None, the subdirectory on the remote SSH server from which to download files.
- Returns:
if everything works, return
'SUCCESS'. If fails, return specific illuminating error messages.- Return type:
See also
- howdy.core.core_rsync.download_upload_files(glob_string, numtries=10, debug_string=False, do_reverse=False, do_local_rsync=False)
Run the system process, using rsync, to download files and directories from, or upload to, the remote SSH server. On completion, the source files are all deleted.
- Parameters:
glob_string (str) – the description of files and directories (such as
'*.mkv'to represent all MKV files) to upload/download.numtries (int) – the number of attempts to run rsync before giving up on uploading or downloading.
debug_string (bool) – if
True, then print out the password-stripped rsync command that is being run.do_reverse (bool) – if
True, then upload files to remote SSH server. IfFalse(the default), then download files from the SSH server.do_local_rsync (bool) – if
True, then instead of SSH-ing do an effectively move command from path =os.path.expanduser( "~", data[ 'subdir' ], mystr )intodata['local_dir']via rsync. This requires that data[‘subdir’] is notNone.
- Returns:
a
tupleof “SUCCESS” and the log of rsync command, otherwise “FAILURE” and specific reason for failure.- Return type:
- howdy.core.core_rsync.get_credentials()
Returns the rsync’ing setup from the SQLite3 configuration database as a
dictin the following form.{ 'local_dir' : XXXX, 'sshpath' : YYYY@ZZZZ, 'password' : AAAA, 'subdir' : BBBB }
- Returns:
the
dictof the rsync’ing setup if in the SQLite3 configuration database, otherwiseNone.- Return type:
See also
- howdy.core.core_rsync.get_rsync_command(data, mystr, do_download=True, do_local_rsync=False)
Returns a
tupleof the actual rsync command, and the command with password information obscured, to download from or upload to the remote SSH server from the Plex server. We require that sshpass_ exists and is accessible on this system.- Parameters:
data – the
dictof rsync’ing configuration, described inget_credentials.mystr (str) – the specific rsync syntax describing those files/folders to upload or download. See, e.g., this website for some practical examples of file or directory listings.
do_download (bool) – if
True, then download from remote SSH server. IfFalse, then upload to remote SSH server.do_local_rsync (bool) – if
True, then instead of SSH-ing do an effectively move command from path =os.path.expanduser( os.path.join( "~", data[ 'subdir' ], mystr ) )intodata['local_dir']via rsync. This requires that data[‘subdir’] is notNone.
- Returns:
a
tupleof the actual rsync command, and the command with password information obscured, to download from or upload to the remote SSH server from the Plex server.- Return type:
- howdy.core.core_rsync.push_credentials(local_dir, sshpath, password, subdir=None)
Push the rsync’ing setup (
local_dir,sshpath,password, andsubdir), if working, into the SQLite3 configuration database.- Parameters:
local_dir (str) – the local directory, on the Plex server, into which to download files from the remote SSH server.
sshpath (str) – the full path with username and host name for the SSH server. Format is
'username@hostname'.password (str) – the password to connect as the SSH server.
subdir (str) – if not
None, the subdirectory on the remote SSH server from which to download files.
- Returns:
if successful, return
'SUCCESS'. If not, return error messages.- Return type:
See also
4.3.6. howdy.core.core_torrents module
This is a newer module. It implements higher level interfaces to the Jackett torrent searching server to search for ebooks. get_book_tor is its only CLI front-end. It also implements some lower-level methods for identifying torrents (files, URLs, binary representations of torrent files, and magnet links), and in string-formatting the information output of torrent servers.
- howdy.core.core_torrents.deconfuse_magnet_link(magnet_string, excluded_tracker_stubs=['stealth.si'])
First functional implementation that returns a magnet string given a
listof torrent tracker stubs to ignore.If one has an invalid magnet_string, then return
None.- Parameters:
magnet_string (str) – the initial magnet string.
excluded_tracker_stubs (list) – the
listof torrent tracker stubs to ignore. Default isget_trackers_to_exclude.
:returns a
strof a magnet string with the problematic torrent tracker stubs inexcluded_tracker_stubsremoved. Ifmagnet_stringis not a valid magnet string, returnNone. :rtype: str
- howdy.core.core_torrents.format_progressbar(progress, width)
Returns a string of a progress bar. This code has been copied from deluge’s f_progressbar.
- Parameters:
progress (float) – a value between 0-100.
- Returns:
str, a progress bar based on width.
- Return type:
Usage
>>> format_progressbar( 87.6, 100 ) '[######################################################################################~~~~~~~~~~~~]'
- howdy.core.core_torrents.format_size(fsize_b)
Formats the bytes value into a string with KiB, MiB or GiB units. This code has been copied from deluge’s format_size.
- Parameters:
fsize_b (int) – the filesize in bytes.
- Returns:
formatted string in KiB, MiB or GiB units.
- Return type:
Usage
>>> format_size( 112245 ) '109.6 KiB'
- howdy.core.core_torrents.format_speed(bps)
Formats a string to display a transfer speed utilizing
fsize(). This is code has been copied from deluge’s format_speed.- Parameters:
bps (int) – bytes per second.
- Returns:
a formatted string representing transfer speed
- Return type:
Usage
>>> format_speed( 43134 ) '42.1 KiB/s'
- howdy.core.core_torrents.format_time(seconds)
Formats the time, in seconds, to a nice format. Unfortunately, the
datetimeclass is too unwieldy for this type of formatting. This code is copied from deluge’s format_time.- Parameters:
seconds (int) – number of seconds.
- Returns:
formatted string in the form of
1 days 03:05:04.- Return type:
Usage
>>> format_time( 97262 ) '1 days 03:01:02'
- howdy.core.core_torrents.get_book_torrent_jackett(name, maxnum=10, keywords=[], verify=True)
Returns a
tupleof candidate book Magnet links found using the main Jackett torrent searching service and the string"SUCCESS", if successful.- Parameters:
name (str) – the book to search for.
maxnum (int) – optional argumeent, the maximum number of magnet links to return. Default is 10. Must be \(\ge 5\).
keywords (list) – optional argument. If not empty, the title of the candidate element must have at least one of the keywords in
keywords.verify (bool) – optional argument, whether to verify SSL connections. Default is
True.
- Returns:
if successful, then returns a two member
tuplethe first member is alistof elements that match the searched episode, ordered from most seeds and leechers to least. The second element is the string"SUCCESS". The keys in each element of the list are,titleis the name of the candidate book to download, and in parentheses the size of the candidate in MB or GB.rawtitlealso the name of the candidate episode to download.seedersis the number of seeds for this Magnet link.leechersis the number of leeches for this Magnet link.linkis the Magnet URI link.torrent_sizeis the size of this torrent in Megabytes.
If this is unsuccessful, then returns an error
tupleof the form returned byreturn_error_raw.- Return type:
- howdy.core.core_torrents.get_trackers_to_exclude()
Returns the
setof torrent tracker stubs to exclude from the reconstruction of magnet links.
- howdy.core.core_torrents.push_trackers_to_exclude(tracker_stubs)
Adds a collection of new torrent tracker stubs to the
PlexExcludedTrackerStubsdatabase.- Parameters:
tracker_stubs (list) – the collection of torrent tracker stubs to add to the database.
- howdy.core.core_torrents.remove_trackers_to_exclude(tracker_stubs)
Removes a collection of candidate torrent tracker stubs to the
PlexExcludedTrackerStubsdatabase.- Parameters:
tracker_stubs (list) – the collection of torrent tracker stubs to remove from the database.
- howdy.core.core_torrents.torrent_format_info(status, torrent_id)
Returns a nicely formatted representation of the status of a torrent.
>>> print( '%s' % torrent_format_info( status, 'ed53ba61555cab24946ebf2f346752805601a7fb' ) ) Name: ubuntu-19.10-beta-desktop-amd64.iso ID: ed53ba61555cab24946ebf2f346752805601a7fb State: Downloading Down Speed: 73.4 MiB/s Up Speed: 0.0 KiB/s ETA: 0 days 00:00:23 Seeds: 24 (67) Peers: 1 (4) Availability: 24.22 Size: 474.5 MiB/2.1 GiB Ratio: 0.000 Seed time: 0 days 00:00:00 Active: 0 days 00:00:05 Tracker status: ubuntu.com: Announce OK Progress: 21.64% [##################################~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]
- Parameters:
status (dict) – the status
dictfor a given torrent, generated fromdeluge_get_torrents_infoortransmission_get_torrents_info.torrent_id (str) – the MD5 hash of that torrent.
- Returns:
a nicely formatted representation of that torrent on the Deluge or Transmission server.
- Return type:
See also
See also
- howdy.core.core_torrents.torrent_is_torrent_file(torrent_file_name)
Check if a file is a torrent file.
- howdy.core.core_torrents.torrent_is_url(torrent_url)
Checks whether an URL is valid, following this prescription.
4.3.7. howdy.core.core_admin module
This is a newer module. It implements the low-level tooling to monitor the Tautulli server that looks at the Plex server, and to check for updates, and download updates to, the current Plex server.
- howdy.core.core_admin.get_tautulli_activity(endpoint, apikey)
- howdy.core.core_admin.get_tautulli_apikey(username, password, endpoint)
Gets the tautulli API key with provided Tautulli username and password.
- howdy.core.core_admin.plex_check_for_update(token, fullURL='http://localhost:32400')
Determines whether there are any new Plex server releases.
- howdy.core.core_admin.plex_download_release(release, token, destination_dir='/Users/tanim/.local/src/howdy/docsrc', do_progress=False)
Downloads the Plex update into a specific directory, with optional progress bar.
- Parameters:
- Returns:
If unsuccessful an error message. If successful, the full path of the downloaded file.
- Return type:
4.3.8. howdy.core.deluge_client_tanim module
This is a newer module. This is a copy of the deluge-client repository and module. Instead of creating a special branch, I had to modify its DelugeRPCClient object to work in a custom way, because of much stricter SSL policies in Python 3.10.
The relevant code that I modify now lives in my DelugeRPCClient. I followed advice from this StackOverflow article on how to set ciphers in SSL Python sockets. I created an SSL context, allowed all ciphers, and then passed the all-ciphers list into the low-level socket that performs RPC communications.
- exception howdy.core.deluge_client_tanim.client.CallTimeoutException
- exception howdy.core.deluge_client_tanim.client.ConnectionLostException
- exception howdy.core.deluge_client_tanim.client.DelugeClientException
Base exception for all deluge client exceptions
- exception howdy.core.deluge_client_tanim.client.FailedToReconnectException
- exception howdy.core.deluge_client_tanim.client.InvalidHeaderException
- class howdy.core.deluge_client_tanim.client.LocalDelugeRPCClient(host='127.0.0.1', port=58846, username='', password='', decode_utf8=True, automatic_reconnect=True)
Client with auto discovery for the default local credentials
- exception howdy.core.deluge_client_tanim.client.RemoteException
4.3.8.1. howdy.core.deluge_client_tanim.rencode submodule
rencode – Web safe object pickling/unpickling.
Public domain, Connelly Barnes 2006-2007.
The rencode module is a modified version of bencode from the BitTorrent project. For complex, heterogeneous data structures with many small elements, r-encodings take up significantly less space than b-encodings:
>>> len(rencode.dumps({'a':0, 'b':[1,2], 'c':99}))
13
>>> len(bencode.bencode({'a':0, 'b':[1,2], 'c':99}))
26
The rencode format is not standardized, and may change with different rencode module versions, so you should check that you are using the same rencode version throughout your project.
- howdy.core.deluge_client_tanim.rencode.dumps(x, float_bits=32)
Dump data structure to str.
Here float_bits is either 32 or 64.