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

157 lines
5.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import ast
import logging
import re
import requests
from odoo import models, fields, api
from odoo.exceptions import UserError
from werkzeug.urls import url_join
_logger = logging.getLogger(__name__)
class SocialLivePostTwitter(models.Model):
_inherit = 'social.live.post'
twitter_tweet_id = fields.Char('Twitter tweet id')
def _compute_live_post_link(self):
twitter_live_posts = self._filter_by_media_types(['twitter']).filtered(
lambda post: post.state == 'posted' and post.account_id.twitter_user_id
)
super(SocialLivePostTwitter, (self - twitter_live_posts))._compute_live_post_link()
for post in twitter_live_posts:
post.live_post_link = 'https://www.twitter.com/%s/statuses/%s' % (
post.account_id.twitter_user_id, post.twitter_tweet_id
)
def _refresh_statistics(self):
super()._refresh_statistics()
accounts = self.env['social.account'].search([('media_type', '=', 'twitter')])
for account in accounts:
existing_live_posts = self.env['social.live.post'].sudo().search(
[('account_id', '=', account.id), ('twitter_tweet_id', '!=', False)],
order='create_date DESC', limit=100)
if not existing_live_posts:
continue
tweets_endpoint_url = url_join(self.env['social.media']._TWITTER_ENDPOINT, '/2/tweets')
query_params = {
'ids': ','.join(existing_live_posts.mapped('twitter_tweet_id')),
'tweet.fields': 'public_metrics',
}
headers = account._get_twitter_oauth_header(
tweets_endpoint_url,
params=query_params,
method='GET'
)
result = requests.get(
tweets_endpoint_url,
params=query_params,
headers=headers,
timeout=5
)
if not result.ok:
_logger.error('Failed to fetch the account (%i) metrics: %r.', account.id, result.text)
result_tweets = result.json().get('data', [])
if isinstance(result_tweets, dict) and result_tweets.get('errors'):
account._action_disconnect_accounts(result_tweets)
return
existing_live_posts_by_tweet_id = {
live_post.twitter_tweet_id: live_post for live_post in existing_live_posts
}
for tweet in result_tweets:
existing_live_post = existing_live_posts_by_tweet_id.get(tweet.get('id'))
if existing_live_post:
public_metrics = tweet.get('public_metrics', {})
likes_count = public_metrics.get('like_count', 0)
retweets_count = public_metrics.get('retweet_count', 0)
existing_live_post.engagement = likes_count + retweets_count
def _post(self):
twitter_live_posts = self._filter_by_media_types(['twitter'])
super(SocialLivePostTwitter, (self - twitter_live_posts))._post()
twitter_live_posts._post_twitter()
def _post_twitter(self):
post_endpoint_url = url_join(self.env['social.media']._TWITTER_ENDPOINT, '/2/tweets')
for live_post in self:
account = live_post.account_id
post = live_post.post_id
params = {
'text': live_post.message,
}
try:
images_attachments_ids = account._format_attachments_to_images_twitter(post.image_ids)
except UserError as e:
live_post.write({
'state': 'failed',
'failure_reason': str(e)
})
continue
if images_attachments_ids:
params['media'] = {'media_ids': images_attachments_ids}
headers = account._get_twitter_oauth_header(post_endpoint_url)
result = requests.post(
post_endpoint_url,
json=params,
headers=headers,
timeout=5
)
if result.ok:
live_post.twitter_tweet_id = result.json()['data']['id']
values = {
'state': 'posted',
'failure_reason': False
}
else:
values = {
'state': 'failed',
'failure_reason': result.text
}
live_post.write(values)
@api.model
def _remove_mentions(self, message, ignore_mentions=None):
"""Remove mentions in the Tweet message.
:param message: text message in which we will look for mention
:param ignore_mentions: do not remove those mentions if found
"""
if not ast.literal_eval(self.env['ir.config_parameter'].sudo().get_param(
'social_twitter.disable_mentions', 'False')):
return message
if ignore_mentions:
# keep only safe (mention consistent) chars in `ignore_mention`
ignore_mentions = [
re.sub(r'[^\w]', '', mention).lower()
for mention in ignore_mentions
]
mention_regex = r'(^|[^\w#])@(%s)\b'
remove_mentions = [
match[2] for match in re.finditer(mention_regex % r'\w+', message)
if not ignore_mentions or match[2].lower() not in ignore_mentions
]
for mention in remove_mentions:
message = re.sub(mention_regex % mention, r'\1@ \2', message)
return message