Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 281 additions & 0 deletions social_media_base/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=================
Social Media Base
=================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:9ef0613fac59ec66dcecfb14f4bff101e89925782f08418a3cf3b64bdf731cd0
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github
:target: https://github.com/OCA/social/tree/19.0/social_media_base
:alt: OCA/social
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/social-19-0/social-19-0-social_media_base
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/social&target_branch=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module provides the fundamental foundation for social media
management. It facilitates the integration of user accounts, posts,
reactions (likes), comments, and graph-based analysis. Designed to be
flexible and scalable, it allows developers and businesses to integrate
and customize social features according to their needs.

Main features:

- Integration of multiple user accounts.
- Basic methods that can be extended and adapted to suit the social
network.
- Basic business structure.
- Campaign group and campaign structure linked to posts, with an
extensible hook so each social network module can import its
campaigns.
- Dashboard of published posts with campaign, video and deletion
indicators.
- Scheduled synchronization of post statistics (monthly cron), plus an
initial synchronization right after an account is linked.
- Account credentials (OAuth tokens) are only visible to administrator
users.

**Table of contents**

.. contents::
:local:

Usage
=====

Generate group campaign.
------------------------

- Go to *Social Media* > Campaigns > Campaign group > New
- A form view opens; fill in the required fields |CREATE_GROUP_CAMPAIGN|
- Save
- The *Campaigns* stat button on the form shows the number of campaigns
of the group and navigates to them.

Generate campaign.
------------------

- Go to *Social Media* > Campaigns > Campaigns > New
- Fill in the fields. The social media is optional; when a social media
is selected, the campaign group and the account become required.
|CREATE_CAMPAIGN|
- Save
- Changes on the main campaign fields are logged in the chatter.
- The native campaign stage bar is hidden in the Social Media views; the
stages keep working in the other applications that use campaigns,
where they can also be managed.

Link a campaign to a post.
--------------------------

- On the post form, select a campaign. Only campaigns whose social media
matches the accounts selected on the post can be chosen.

- The campaign is shown as a badge on the post kanban and on the
dashboard cards.

|DASHBOARD|

Posts on the dashboard.
-----------------------

- Posts that contain a video display a video indicator on their card,
and the posts kanban shows a *Video (N)* counter.

- Posts deleted directly on the social network are marked as *Deleted on
<media>* and kept in the dashboard as history.

|POSTS_KANBAN|

Charts.
-------

- Go to *Social Media* > Charts

- The view shows one chart per connected account with the statistics of
its publications. The statistics are requested to the social networks
when the view is opened, so a loader is displayed until they are
available.

|CHARTS|

Ads.
----

- Go to *Social Media* > Campaigns > Ads

- The view lists the sponsored creatives of the connected accounts, each
one with its status, its campaign and the post it promotes. Clicking
an ad opens it on the social network.

- The status is the one set by the advertiser on the social network; the
reason why the network is serving the ad or not is shown in the
tooltip of the badge.

- The ads can be filtered by creation date and by text, which is
searched in the campaign name, the post name and the status. The *Sync
ads* button refreshes them from the social networks.

|ADS|

Archive an account.
-------------------

- The account form provides an *Archive account* button, available to
the user responsible for the account.

|ACCOUNT_FORM|

- Archiving an account also archives its dashboard posts, campaigns,
campaign groups and the posts linked only to that account.

- Nothing is removed from the social network, and unarchiving the
account restores everything.

Delete an account permanently.
------------------------------

- The account form provides a *Delete permanently* button, available
only to the *Social Media / Administrator* group. A regular user can
only archive his accounts, he is not allowed to delete them.
- It deletes the account, its dashboard publications and the posts that
were linked only to that account, together with their metrics,
comments and attachments.
- Campaigns and campaign groups are **not** deleted, they only lose
their link to the account: campaigns are shared with the other Odoo
applications and may be linked to leads, orders or mailings.
- Nothing is deleted from the social network: the publications stay
online.
- This cannot be undone. To keep the history, archive the account
instead.

Statistics synchronization.
---------------------------

- The scheduled action *Social: Sync posts statistics* updates the post
statistics monthly.
- An initial synchronization is also triggered automatically right after
an account is linked.

Import campaigns.
-----------------

- The account form provides an *Import campaigns* button. Each social
network module implements the actual import; a notification shows the
result.

Account ownership.
------------------

- Every account has a *Responsible* user, set to whoever linked it. A
regular user of the *Social Media / User: Own Accounts* group only
sees and manages his own accounts, their posts, campaigns and
statistics.
- Linking an account that already exists in Odoo (relinking it after
archiving it, after reinstalling the connector or to renew its tokens)
is restricted to that responsible user and to the *Social Media /
Administrator* group, because it overwrites the credentials and the
access tokens stored in the account.
- Accounts are recognised by the identifier they have on the social
network, not by their name: renaming the account on the social network
keeps the history in Odoo, and a name reused by a different account
never overwrites an existing one.
- If another user completes the association of an account that is not
his, nothing is written and a notification explains that the account
belongs to somebody else. The same happens when the administrator of
the wizard tries to change the credentials of an account that is not
his.
- The *Update account* and *Archive account* buttons of the account form
are shown to the responsible user and to the *Social Media /
Administrator* group. The credentials themselves (client keys and
tokens) stay hidden from everybody but the system administrators, and
the connectors read and write them internally, so an administrator of
the application can renew them without ever seeing them.

Campaign badge.
---------------

- The publications of the dashboard and of the posts kanban show the
campaign they belong to as a badge. Long campaign names are shortened
with an ellipsis so the card keeps its shape, and the whole name is
available in the tooltip.
- Clicking the badge opens that campaign in Odoo, so its budget, its
status on the social network and its history are one click away from
the post.

.. |CREATE_GROUP_CAMPAIGN| image:: https://raw.githubusercontent.com/OCA/social/19.0/social_media_base/static/img/readme/CREATE_GROUP_CAMPAIGN.png
.. |CREATE_CAMPAIGN| image:: https://raw.githubusercontent.com/OCA/social/19.0/social_media_base/static/img/readme/CREATE_CAMPAIGN.png
.. |DASHBOARD| image:: https://raw.githubusercontent.com/OCA/social/19.0/social_media_base/static/img/readme/DASHBOARD.png
.. |POSTS_KANBAN| image:: https://raw.githubusercontent.com/OCA/social/19.0/social_media_base/static/img/readme/POSTS_KANBAN.png
.. |CHARTS| image:: https://raw.githubusercontent.com/OCA/social/19.0/social_media_base/static/img/readme/CHARTS.png
.. |ADS| image:: https://raw.githubusercontent.com/OCA/social/19.0/social_media_base/static/img/readme/ADS.png
.. |ACCOUNT_FORM| image:: https://raw.githubusercontent.com/OCA/social/19.0/social_media_base/static/img/readme/ACCOUNT_FORM.png

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/social/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/social/issues/new?body=module:%20social_media_base%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* BinhexTeam

Contributors
------------

- [Binhex Cloud] (https://www.binhex.cloud):

- Edilio Escalona Almira e.escalona@binhex.cloud

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-edescalona| image:: https://github.com/edescalona.png?size=40px
:target: https://github.com/edescalona
:alt: edescalona

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-edescalona|

This module is part of the `OCA/social <https://github.com/OCA/social/tree/19.0/social_media_base>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
11 changes: 11 additions & 0 deletions social_media_base/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright 2025 Binhex <https://www.binhex.cloud>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import controllers
from . import models
from . import wizards


def remove_social_media(env, media_type):
"""Remove the data of a social media, called from a connector ``uninstall_hook``."""
env["social.account"]._remove_social_media(media_type)
49 changes: 49 additions & 0 deletions social_media_base/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright 2025 Binhex <https://www.binhex.cloud>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Social Media Base",
"summary": "Basic module for social media management.",
"version": "19.0.1.0.0",
"category": "Social Network",
"development_status": "Beta",
"license": "AGPL-3",
"author": "BinhexTeam,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/social",
"maintainers": ["edescalona"],
"depends": ["base", "web", "mail", "utm"],
"data": [
"security/social_media_base_groups.xml",
"security/ir.model.access.csv",
"security/social_account_security.xml",
"security/social_post_security.xml",
"security/social_post_account_security.xml",
"security/wizard_social_account_security.xml",
"data/ir_cron_data.xml",
"views/social_media_views.xml",
"views/social_account_views.xml",
"views/social_post_views.xml",
"views/social_post_account_views.xml",
"views/utm_group_campaign_views.xml",
"views/utm_campaign_views.xml",
"views/social_action_client_views.xml",
"wizards/wizard_social_account.xml",
"views/social_media_base_menus.xml",
],
"assets": {
"web.assets_backend": [
("include", "web.chartjs_lib"),
"social_media_base/static/src/xml/**/*.xml",
"social_media_base/static/src/scss/**/*.scss",
"social_media_base/static/src/js/app/**/*.js",
"social_media_base/static/src/js/services/**/*.js",
"social_media_base/static/src/components/**/*.xml",
"social_media_base/static/src/components/**/*.js",
"social_media_base/static/src/components/**/*.scss",
"social_media_base/static/src/js/views/**/*.xml",
"social_media_base/static/src/js/views/**/*.scss",
"social_media_base/static/src/js/views/**/*.js",
],
},
"exclude": ["social"],
"installable": True,
}
4 changes: 4 additions & 0 deletions social_media_base/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2025 Binhex <https://www.binhex.cloud>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import thread
39 changes: 39 additions & 0 deletions social_media_base/controllers/thread.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2025 Binhex <https://www.binhex.cloud>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.http import request, route

from odoo.addons.mail.controllers.thread import ThreadController
from odoo.addons.mail.tools.discuss import add_guest_to_context


class ThreadControllerSocial(ThreadController):
def _prepare_result(self):
return {
"author": {
"id": request.env.user.partner_id.id,
"name": request.env.user.partner_id.name,
"is_company": request.env.user.partner_id.is_company,
"user": {
"id": request.env.uid,
"isInternalUser": request.env.user._is_internal(),
},
"type": "partner",
}
}

@route("/mail/message/post", methods=["POST"], type="jsonrpc", auth="public")
@add_guest_to_context
def mail_message_post(self, thread_model, thread_id, post_data, context=None):
if thread_model == "social.post.account" and thread_id:
post = request.env[thread_model].browse(int(thread_id)).exists()
if not post:
return None
post.check_access_rights("write")
post.check_access_rule("write")
comment = post.create_comment(post_data, context)
request.env["bus.bus"]._sendone(
request.env.user.partner_id, "comments", comment
)
return self._prepare_result()
return super().mail_message_post(thread_model, thread_id, post_data, context)
Loading
Loading