integration_models.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import json
  2. from django.db import models
  3. from django.forms.widgets import Input
  4. from django.template import Context
  5. from django.template import Template
  6. from django.template.loader import render_to_string
  7. from django.utils.translation import gettext_lazy as _
  8. from wagtail import hooks
  9. from wagtail.admin.panels import FieldPanel
  10. from coderedcms.api.mailchimp import MailchimpApi
  11. class MailchimpSubscriberIntegrationWidget(Input):
  12. template_name = (
  13. "coderedcms/formfields/mailchimp/subscriber_integration_widget.html"
  14. )
  15. js_template_name = (
  16. "coderedcms/formfields/mailchimp/subscriber_integration_js.html"
  17. )
  18. def get_context(self, name, value, attrs):
  19. ctx = super(MailchimpSubscriberIntegrationWidget, self).get_context(
  20. name, value, attrs
  21. )
  22. json_value = self.get_json_value(value)
  23. list_library = self.build_list_library()
  24. ctx["widget"]["value"] = json.dumps(json_value)
  25. ctx["widget"]["extra_js"] = self.render_js(
  26. name, list_library, json_value
  27. )
  28. ctx["widget"]["selectable_mailchimp_lists"] = (
  29. self.get_selectable_mailchimp_lists(list_library)
  30. )
  31. ctx["widget"]["stored_mailchimp_list"] = self.get_stored_mailchimp_list(
  32. json_value
  33. )
  34. return ctx
  35. def render_js(self, name, list_library, json_value):
  36. ctx = {
  37. "widget_name": name,
  38. "widget_js_name": name.replace("-", "_"),
  39. "list_library": list_library,
  40. "stored_mailchimp_list": self.get_stored_mailchimp_list(json_value),
  41. "stored_merge_fields": self.get_stored_merge_fields(json_value),
  42. }
  43. return render_to_string(self.js_template_name, ctx)
  44. def get_json_value(self, value):
  45. if value:
  46. json_value = json.loads(value)
  47. else:
  48. json_value = json.loads("{}")
  49. if "list_id" not in json_value:
  50. json_value["list_id"] = ""
  51. if "merge_fields" not in json_value:
  52. json_value["merge_fields"] = {}
  53. if "email_field" not in json_value:
  54. json_value["email_field"] = ""
  55. if "interest_categories" not in json_value:
  56. json_value["interest_categories"] = {}
  57. return json_value
  58. def get_stored_mailchimp_list(self, value):
  59. if "list_id" in value:
  60. return str(value["list_id"])
  61. def get_stored_merge_fields(self, value):
  62. if "merge_fields" in value:
  63. return json.dumps(value["merge_fields"])
  64. return json.dumps({})
  65. def get_selectable_mailchimp_lists(self, library):
  66. selectable_lists = [("", "--- Select a Mailchimp List ---")]
  67. for k, v in library.items():
  68. selectable_lists.append((k, v["name"]))
  69. return selectable_lists
  70. def build_list_library(self):
  71. mailchimp = MailchimpApi()
  72. list_library = {}
  73. if mailchimp.is_active:
  74. lists = mailchimp.get_lists()
  75. for mlist in lists["lists"]:
  76. list_library[mlist["id"]] = {
  77. "name": mlist["name"],
  78. "merge_fields": {},
  79. "interest_categories": {},
  80. }
  81. list_library[mlist["id"]]["merge_fields"] = (
  82. mailchimp.get_merge_fields_for_list(
  83. mlist["id"]
  84. )["merge_fields"]
  85. )
  86. list_library[mlist["id"]]["interest_categories"] = (
  87. mailchimp.get_interest_categories_for_list(
  88. mlist["id"]
  89. )["categories"]
  90. )
  91. for category in list_library[mlist["id"]][
  92. "interest_categories"
  93. ]:
  94. category["interests"] = (
  95. mailchimp.get_interests_for_interest_category(
  96. mlist["id"], category["id"]
  97. )["interests"]
  98. )
  99. return list_library
  100. class MailchimpSubscriberIntegration(models.Model):
  101. class Meta:
  102. abstract = True
  103. subscriber_json_data = models.TextField(blank=True, verbose_name=_("List"))
  104. def integration_operation(self, instance, **kwargs):
  105. mailchimp = MailchimpApi()
  106. if mailchimp.is_active:
  107. submission_dict = kwargs["form_submission"].get_data()
  108. rendered_dictionary = self.render_dictionary(submission_dict)
  109. mailchimp.add_user_to_list(
  110. list_id=self.get_list_id(), data=rendered_dictionary
  111. )
  112. def get_data(self):
  113. return json.loads(self.subscriber_json_data)
  114. def get_merge_fields(self):
  115. if "merge_fields" in self.get_data():
  116. return self.get_data()["merge_fields"]
  117. return {}
  118. def get_list_id(self):
  119. if "list_id" in self.get_data():
  120. return self.get_data()["list_id"]
  121. def combine_interest_categories(self):
  122. interest_dict = {}
  123. for category_id, value in self.get_data()[
  124. "interest_categories"
  125. ].items():
  126. interest_dict.update(value["interests"])
  127. return interest_dict
  128. def render_dictionary(self, form_submission):
  129. rendered_dictionary_template = json.dumps(
  130. {
  131. "members": [
  132. {
  133. "email_address": self.get_data()["email_field"],
  134. "merge_fields": self.get_data()["merge_fields"],
  135. "interests": self.combine_interest_categories(),
  136. "status": "subscribed",
  137. }
  138. ],
  139. "update_existing": True,
  140. }
  141. )
  142. rendered_dictionary = Template(rendered_dictionary_template).render(
  143. Context(form_submission)
  144. )
  145. return rendered_dictionary
  146. panels = [
  147. FieldPanel(
  148. "subscriber_json_data", widget=MailchimpSubscriberIntegrationWidget
  149. )
  150. ]
  151. @hooks.register("form_page_submit")
  152. def run_mailchimp_subscriber_integrations(instance, **kwargs):
  153. if hasattr(instance, "integration_panels"):
  154. for panel in instance.integration_panels:
  155. for integration in getattr(instance, panel.relation_name).all():
  156. integration.integration_operation(instance, **kwargs)