import requests from celery.utils.log import get_task_logger from django.utils import timezone from pingcap_sso.celery import app as celery_app from pingcap_sso.models import LarkMessage, SiteSetting, PingCAPLarkStaff logger = get_task_logger(__name__) @celery_app.task(bind=True) def send_lark_message(self, message_id): try: message = LarkMessage.objects.get(id=message_id) except LarkMessage.DoesNotExist: logger.error(f'LarkMessage {message_id} does not exist') return if message.status == LarkMessage.STATUS_SUCCESS: return sync_success, response_body = False, None try: resp = requests.post( message.webhook, data=message.payload, headers={"Content-Type": "application/json"}, timeout=5 ) if resp.status_code != 200: sync_success = False logger.error( f'send message({message_id}) to lark failed, status: {resp.status_code}') elif resp.json().get('StatusCode') != 0: sync_success = False logger.error( f'send message({message_id}) to lark failed') else: sync_success = True response_body = resp.content.decode('utf8') except Exception as e: logger.error(e) response_body = str(e) message.send_at = timezone.now() message.status = LarkMessage.STATUS_SUCCESS if sync_success else LarkMessage.STATUS_FAILED message.response_body = response_body message.save(update_fields=['send_at', 'status', 'response_body']) # retry if failed if not sync_success: self.apply_async(args=[message_id], countdown=60 * 5) return sync_success @celery_app.task def handle_lark_staff_resigned_event(org, event_body): if org != 'cn': return message = f"""**员工离职通知** - 组织: { org } - 姓名: { event_body.get('name') }""" LarkMessage.send( webhook=SiteSetting.pingcap_staff_resigned_notify_lark_webhook, message_type=LarkMessage.MESSAGE_TYPE_MARKDOWN, content=message, remark='员工离职通知', # Celery worker 不在这个事务中, 它没法立刻读到这条记录, 所以延迟 10 秒发送, 这个事务应在 10 秒内结束 send_countdown=10, ) # event_body: https://open.feishu.cn/document/server-docs/contact-v3/user/events/deleted lark_user_id = event_body['open_id'] try: lark_staff = PingCAPLarkStaff.objects.get(lark_user_id=lark_user_id) except PingCAPLarkStaff.DoesNotExist: # does not grant staff permission, ignore return user = lark_staff.user if not user: # already unbind, ignore return user.is_staff = False user.is_superuser = False user.groups.clear() user.user_permissions.clear() user.save() lark_staff.is_activated = False lark_staff.is_resigned = True lark_staff.user = None lark_staff.save() logger.info(f'Unbind lark staff {lark_user_id} from {user.username}')