1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/social/models/social_live_post.py
2024-12-10 09:04:09 +07:00

123 lines
5.4 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
import requests
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class SocialLivePost(models.Model):
""" A social 'live' post, as opposed to a social.post, represents a post that is
actually on a social.account instance.
Basically, a social.post that is posted on 4 social.accounts will create 4 instances
of the social.live.post. """
_name = 'social.live.post'
_description = 'Social Live Post'
post_id = fields.Many2one('social.post', string="Social Post", required=True, readonly=True, ondelete="cascade")
account_id = fields.Many2one('social.account', string="Social Account", required=True, readonly=True, ondelete="cascade")
message = fields.Char('Message', compute='_compute_message',
help="Content of the social post message that is post-processed (links are shortened, UTMs, ...)")
live_post_link = fields.Char('Post Link', compute='_compute_live_post_link',
help="Link of the live post on the target media.")
failure_reason = fields.Text('Failure Reason', readonly=True,
help="""The reason why a post is not successfully posted on the Social Media (eg: connection error, duplicated post, ...).""")
state = fields.Selection([
('ready', 'Ready'),
('posting', 'Posting'),
('posted', 'Posted'),
('failed', 'Failed')],
string='Status', default='ready', required=True, readonly=True,
help="""Most social.live.posts directly go from Ready to Posted/Failed since they result of a single call to the third party API.
A 'Posting' state is also available for those that are sent through batching (like push notifications).""")
engagement = fields.Integer("Engagement", help="Number of people engagements with the post (Likes, comments...)")
company_id = fields.Many2one('res.company', 'Company', related='account_id.company_id')
@api.depends(lambda self:
['post_id.message', 'post_id.utm_campaign_id', 'account_id.media_type', 'account_id.utm_medium_id', 'post_id.source_id'] +
['post_id.%s' % field for field in self.env['social.post']._get_post_message_modifying_fields()])
def _compute_message(self):
""" Prepares the message of the parent post, and shortens links to contain UTM data. """
for live_post in self:
message = self.env['mail.render.mixin'].sudo()._shorten_links_text(
live_post.post_id.message,
live_post._get_utm_values())
live_post.message = self.env['social.post']._prepare_post_content(
message,
live_post.account_id.media_type,
**{field: live_post.post_id[field] for field in self.env['social.post']._get_post_message_modifying_fields()})
@api.depends('account_id.media_id')
def _compute_live_post_link(self):
for live_post in self:
live_post.live_post_link = False
@api.depends('state', 'account_id')
def _compute_display_name(self):
""" ex: [Facebook] Odoo Social: posted, [Twitter] Mitchell Admin: failed, ... """
state_description_values = dict(self._fields['state']._description_selection(self.env))
for live_post in self:
live_post.display_name = f'{live_post.account_id.display_name}: {state_description_values.get(live_post.state)}'
@api.model_create_multi
def create(self, vals_list):
res = super(SocialLivePost, self).create(vals_list)
res.mapped('post_id')._check_post_completion()
return res
def write(self, vals):
res = super(SocialLivePost, self).write(vals)
if vals.get('state'):
self.mapped('post_id')._check_post_completion()
return res
def action_retry_post(self):
self._post()
@api.model
def refresh_statistics(self):
# as refreshing the statistics is a recurring task, we ignore occasional "read timeouts"
# from the third party services, as it would most likely mean a temporary slow connection
# and/or a slow response from their side
try:
self.env['social.live.post']._refresh_statistics()
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
_logger.warning("Failed to refresh the live post statistics.", exc_info=True)
def _refresh_statistics(self):
""" Every social module should override this method.
This is the method responsible for fetching the post data per social media.
It will be called manually every time we need to refresh the social.stream data:
- social.stream creation/edition
- 'Feed' kanban loading
- 'Refresh' button on 'Feed' kanban
- ...
"""
pass
def _post(self):
""" Every social module should override this method.
This will make the actual post on the related social.account through the third party API """
pass
def _get_utm_values(self):
self.ensure_one()
post_id = self.post_id
return {
'campaign_id': post_id.utm_campaign_id.id,
'medium_id': self.account_id.utm_medium_id.id,
'source_id': post_id.source_id.id,
}
def _filter_by_media_types(self, media_types):
return self.filtered(lambda post: post.account_id.media_id.media_type in media_types)