Social Media X
social_media_x · OCA/social
-
Security25/25No findings
-
Activity25/25Human commit this month
-
Required by5/250 modules depend on it
-
Maturity5/25In 1 Odoo series since 17.0
Heuristic over the facts below, not an audit · How it's computed
Description
This module provides the necessary functionality for basic interaction with the X social media.
Main features:
- User account integration.
- Post creation.
- Reports with agnostic metrics, on the account card of the Dashboard. The figures are read back from X by the connector itself: the publications of the last 30 days are refreshed once a day, and the card of the account adds up the counters its publications hold. A synchronization module widens what is known — the publications Odoo did not send, and the history older than that window — but the card is not empty without one.
- Reposts and quotes, the two figures only X reports. They are shown as Reposts and Quotes in the Statistics dialog of a publication, opened from the menu of its card on the Dashboard, and they count towards the Interactions total and the Engagement rate of the publication and of the account.
- What X will not publish, shown on the post while it is written. The message is checked against the characters the plan of the account allows, 280 without X Premium and 25 000 with it, and the medias against 4 images of at most 5 MB each — 15 MB for a GIF — in JPG, PNG, WEBP or GIF, and one video of at most 512 MB in MP4. X takes images or a video, never both in the same post, so a post mixing them is refused instead of warned about. The same checks refuse the publication if the post reaches it anyway, through an import or an RPC call.
- The credit balance of the developer App that pays the calls to the X API, on the account form. It is read from X every 2 hours and from the buttons of the account, and the responsible of the account is warned when it drops under a threshold set on the account or is used up.
An X account will never draw a time series in Social Media > Statistics. That screen reads a history per day, and the metrics the API v2 answers are the current lifetime counters of each post, with no way of asking for them grouped by day. Giving X a series means either repeating the lifetime counter on every day, which draws a cumulative curve of a different shape than the other social media on the same graph, or storing the delta between two readings, which is false for any day the scheduled action did not run. Neither is a measurement, so nothing is written: an account of X shows the standard empty view there, and its figures live on its card of the Dashboard, which is where they mean something.
Dependencies
Code analysis
Extracted from the source by best-effort static analysis (no code is executed); details may be incomplete.
Views touched 3
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
social_account_view_form_inherit |
social.account.view.form.inherit.x | social.account | form | Inherits social_media_base.social_account_view_form |
social_post_account_view_form_statistics_inherit |
social.post.account.view.form.statistics.inherit.social.media.x | social.post.account | form | Inherits social_media_base.social_post_account_view_form_statistics |
wizard_social_account_view_form_inherit |
wizard.social.account.view.form.inherit.x | wizard.social.account | form | Inherits social_media_base.wizard_social_account_view_form |
HTTP endpoints 1
| Route(s) | Handler | Auth | Type | Methods | Flags |
|---|---|---|---|---|---|
/social_x/callback |
SocialMediaX.social_x |
user | http | ALL | sudo |
Models touched 6
-
rate_limit_endpointJsoncopy=Falsedefault=dict -
x_access_secret_oauth1Chargroups='base.group_system' -
x_access_token_oauth1Chargroups='base.group_system'help='Post and delete'string='Token for write' -
x_access_token_oauth2Chargroups='base.group_system'help='App-only bearer token, obtained from the API Key and the API Secret. It authorizes what is asked in the name of the App and not of a user.'string='Token for read' -
x_api_keyChargroups='base.group_system'help='The API Key of the developer App, which the X Developer Console lists under OAuth 1.0 Keys as the Consumer Key. Regenerating it in the Console invalidates the one stored here.'string='API Key' -
x_api_secretChargroups='base.group_system'help='The API Key Secret of the developer App, shown by the X Developer Console only when the Consumer Key is generated. Regenerating it in the Console invalidates the one stored here.'string='API Secret' -
x_credit_balanceFloatcopy=Falsedigits=(16, 2)help='What is left of the credits the developer App bought to pay for the calls to the X API. It is the balance of the App and not of this account, so the accounts holding the same API Key share it. It is read again every 2 hours and when the account is associated, updated or its statistics refreshed.'readonly=Truestring='Credit Balance (USD)' -
x_credit_balance_dateDatetimecopy=Falsehelp='When X last answered the credit balance.'readonly=Truestring='Credit Balance Read On' -
x_credit_warnedBooleancopy=Falsehelp='Whether the responsible was already warned that the credit balance is under the warning threshold. Cleared when the balance is read again at or over it, so the warning is given once per drop.'readonly=True -
x_credit_warningFloatdefault=1.0digits=(16, 2)help='The responsible of the account is warned when the credit balance drops under this amount. At 0, only when it is used up.'string='Credit Warning (USD)' -
x_premiumBooleancopy=Falsedefault=Falsehelp='Whether the X user of this account holds an X Premium subscription, which raises the message of a post from 280 to 25 000 characters. Read from X when the account is associated and on Update account, so a subscription bought or cancelled later is seen after pressing Update account.'readonly=True
-
action_refresh_statistics(self)Read the credit balance of the App as well, for an X account. -
action_update_account(self) -
create_account_x(self, x_access_token_oauth1, x_access_secret_oauth1, kwargs)Create or update the account of the authorized X user. An existing account is only reused when the current user is allowed to associate it, and it is reactivated if it was archived. -
create_tweet(self, message, image_ids, video_ids, post_id, post_account_id)Publish a post with its media. The rate limit is answered here, because it is not a failure of the post but a time to wait, and the user is told when to try again. Everything else is left to the caller: the publication guard records it on the line, with its reason, which is where the user looks for it afterwards. A ``401`` is raised as a credentials error: X answers it for a token it no longer accepts, and since X has no way to renew the token from Odoo, the account is flagged for the user to authorize it again. A ``400`` or a ``403`` is a post X refuses, not a token it rejects: the cause is the plan of the App, the plan of the account, the permissions of the App or the content, and none of them is fixed by authorizing the account again. They are raised as a user error with the reason told by :meth:`~._x_refused_post_message`, and the account is left as it is. The upload of the medias runs inside the same guard, so a media X refuses is explained the same way. The references of the medias travel back with the identifier of the tweet, so the publication stores in one write what it published and what X called each of its medias. :return: The id of the published tweet or False, and the ``media_id`` of each media keyed by the identifier of its attachment. :rtype: tuple -
get_client_api(self, client_api=True, x_access_token_oauth1=None, x_access_secret_oauth1=None, bearer_token=None, kwargs=None)Build the tweepy client for this account. ``client_api`` returns the API v2 client, which serves every endpoint of X but the upload of medias; otherwise the v1.1 client, still needed for that upload. :rtype: tweepy.Client | tweepy.API
-
media_typeSelectionondelete={'x': 'cascade'}selection_add=[('x', 'X')]
-
action_open_account(self)
No new fields.
Public methods (0)No public methods.
No new fields.
Public methods (0)No public methods.
-
quote_countIntegerdefault=0 -
retweet_countIntegerdefault=0
No public methods.
-
oauth_tokenChar -
x_api_keyCharhelp='The API Key of the developer App, which the X Developer Console lists under OAuth 1.0 Keys as the Consumer Key. Regenerating it in the Console invalidates the one stored here.'string='API Key' -
x_api_secretCharhelp='The API Key Secret of the developer App, shown by the X Developer Console only when the Consumer Key is generated. Regenerating it in the Console invalidates the one stored here.'string='API Secret'
No public methods.
Loading…