Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5775cbf
Mod. ContactEncoder. Memorizing your buffering level, clearing levels…
AntonV1211 Sep 29, 2026
0e5cbcb
Dev. Code. Tests
AntonV1211 Sep 29, 2026
e8dc269
Fix. ContactEncoder. Default value for method
AntonV1211 Sep 30, 2026
30cc001
Merge pull request #899 from CleanTalk/fix_buff_level_av
AntonV1211 Oct 5, 2026
a21a802
Version: 6.89.99-dev
alexandergull Oct 5, 2026
b059b1c
Merge branch 'master' into fix
alexandergull Oct 5, 2026
53240af
Version: 6.89.99-fix
alexandergull Oct 5, 2026
674d3cb
Upd. Contacts encoder. Short codes functionality optimized. (#900)
Glomberg Oct 5, 2026
7a89153
New. Integrations. BuddyNext plugin registration.
alexandergull Oct 8, 2026
d96a45d
Merge branch 'fix' into buddynext_int.ag
alexandergull Oct 8, 2026
eba5834
Dev. Unit test.
alexandergull Oct 8, 2026
bd5c0cf
Merge remote-tracking branch 'origin/master' into dev
Glomberg Oct 8, 2026
b6cca1a
Fix. ContactEncoder. Edit to the tag attribute definition
AntonV1211 Oct 12, 2026
140bcdb
Fix. Code. Replacing the first occurrence of the search only in the e…
AntonV1211 Oct 12, 2026
0e6b3c9
Dev. Common. Sync common lib
AntonV1211 Oct 12, 2026
5eb7ec6
Dev. Code. Unit tests
AntonV1211 Oct 12, 2026
971da4c
Dev. Code. Sync common lib
AntonV1211 Oct 12, 2026
d05b8d0
Dev. Code. Fix copilot review
AntonV1211 Oct 12, 2026
18d8984
Dev. Code. Improve external flow.
svedge Oct 12, 2026
de6241f
Dev. Code. Improve formidable flow.
svedge Oct 12, 2026
b6dd817
Dev. Code. Common lib updated.
Glomberg Oct 12, 2026
183c9d9
Fix. Code. Parsing the response and text output
AntonV1211 Oct 13, 2026
c4057a8
Merge branch 'dev' of https://github.com/CleanTalk/wordpress-antispam…
AntonV1211 Oct 13, 2026
ca5b760
Fix. Force protection. Checking bot detector fixed.
Glomberg Oct 13, 2026
6ced086
Dev. Code. Improve external flow.
svedge Oct 13, 2026
c277642
Dev. Code. Improve formidable flow.
svedge Oct 13, 2026
31122c0
Merge pull request #906 from CleanTalk/vuln_kses_av
AntonV1211 Oct 13, 2026
d934a03
Dev. ContactEncoder. Fixed title encoding for private posts.
alexandergull Oct 13, 2026
69890aa
Dev. Common. Sync common lib.
AntonV1211 Oct 13, 2026
8ebc19a
Merge pull request #905 from CleanTalk/vuln_xss_av
AntonV1211 Oct 13, 2026
6ec0531
Fix. Comments checker. Feedback success message fixed. (#907)
Glomberg Oct 13, 2026
470d98e
Fxi. ContactEncoder. Common lib updates.
alexandergull Oct 13, 2026
b69acc5
Dev. Code. Publish SVN from the filtered master tree and open a PSC t…
AntonV1211 Oct 13, 2026
5ec45ee
Merge branch 'dev' of https://github.com/CleanTalk/wordpress-antispam…
AntonV1211 Oct 13, 2026
f105b52
Dev. Common. Sync common lib
AntonV1211 Oct 13, 2026
06101f2
Dev. Code. Merge dev, fix
AntonV1211 Oct 13, 2026
fe16215
Dev. Code. Update version 6.90
AntonV1211 Oct 13, 2026
1f1532f
chore(changelog): rebuild readme for v6.90 [skip ci]
github-actions[bot] Oct 13, 2026
19e7b49
Dev. CICD. Update svn action.
AntonV1211 Oct 14, 2026
1c72ebb
Dev. Integrations. BuddyBoss login page exclusion removed.
alexandergull Oct 14, 2026
4788cae
Dev. Users checker. Flow of non-checkable users improved.
alexandergull Oct 14, 2026
7575490
Merge branch 'beta' of https://github.com/CleanTalk/wordpress-antispa…
AntonV1211 Oct 15, 2026
721c5e9
Merge branch 'master' of https://github.com/CleanTalk/wordpress-antis…
AntonV1211 Oct 15, 2026
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
2 changes: 2 additions & 0 deletions .7zignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ LICENSE
psalm.xml
composer.json
composer.lock
webpack.config.js
codecov.yml
.*
42 changes: 42 additions & 0 deletions .github/actions/create-psc-task/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Create PSC task
description: Open a doBoard PSC task for the pentest duty shift, or only log that task
inputs:
version:
required: true
plugin_slug:
required: true
create_task:
required: true
default: "false"
role_name:
required: false
default: "Pentesting on Duty"
doboard_username:
required: true
doboard_password:
required: true
doboard_company_id:
required: true
default: "1"
doboard_project_id:
required: true
default: "78"
doboard_track_id:
required: true
default: "1537"
runs:
using: composite
steps:
- name: Resolve PSC task
shell: bash
env:
INPUT_VERSION: ${{ inputs.version }}
INPUT_PLUGIN_SLUG: ${{ inputs.plugin_slug }}
INPUT_CREATE_TASK: ${{ inputs.create_task }}
INPUT_ROLE_NAME: ${{ inputs.role_name }}
DOBOARD_USERNAME: ${{ inputs.doboard_username }}
DOBOARD_PASSWORD: ${{ inputs.doboard_password }}
DOBOARD_COMPANY_ID: ${{ inputs.doboard_company_id }}
DOBOARD_PROJECT_ID: ${{ inputs.doboard_project_id }}
DOBOARD_TRACK_ID: ${{ inputs.doboard_track_id }}
run: python3 ${{ github.action_path }}/psc_task.py
201 changes: 201 additions & 0 deletions .github/actions/create-psc-task/psc_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
#!/usr/bin/env python3
"""Resolve the pentest duty user and, unless create_task is false, open a PSC task."""

import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request
from datetime import datetime, timedelta, timezone


ROLE_NAME_DEFAULT = "Pentesting on Duty"
AUTH_URL = "https://api-ctask.cleantalk.org/user_authorize"


class ApiError(Exception):
pass


def env(name, default=""):
return os.environ.get(name, default).strip()


def require(name):
value = env(name)
if not value:
raise ApiError(f"Required environment variable is empty: {name}")
return value


def post(url, fields):
data = urllib.parse.urlencode(fields).encode("utf-8")
request = urllib.request.Request(
url,
data=data,
method="POST",
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
try:
with urllib.request.urlopen(request, timeout=30) as response:
raw = response.read().decode("utf-8")
except urllib.error.HTTPError as exc:
body = exc.read().decode("utf-8", errors="replace")
raise ApiError(f"HTTP {exc.code} from {url}: {body}") from exc
except urllib.error.URLError as exc:
raise ApiError(f"Request to {url} failed: {exc.reason}") from exc
try:
return json.loads(raw)
except json.JSONDecodeError as exc:
raise ApiError(f"Non-JSON response from {url}: {raw}") from exc


def authorize():
result = post(
AUTH_URL,
{
"email": require("DOBOARD_USERNAME"),
"password": require("DOBOARD_PASSWORD"),
},
)
session_id = (result.get("data") or {}).get("session_id")
if not session_id:
raise ApiError("Auth failed")
return session_id


def company_url(route):
company_id = env("DOBOARD_COMPANY_ID", "1")
return f"https://api.doboard.com/{company_id}/{route}"


def role_id(session_id, role_name):
result = post(company_url("role_get"), {"session_id": session_id})
roles = (result.get("data") or {}).get("roles")
if not isinstance(roles, list):
raise ApiError("Roles not found")
for role in roles:
if role.get("name") == role_name:
return role.get("role_id")
raise ApiError(f"Role not found: {role_name}")


def duty_user_id(session_id, wanted_role_id):
today = datetime.now(timezone.utc).date()
result = post(
company_url("calendar_events_get"),
{
"session_id": session_id,
"period_begin": today.isoformat(),
"period_end": (today + timedelta(days=1)).isoformat(),
"role_id": wanted_role_id,
},
)
events = (result.get("data") or {}).get("events")
if not isinstance(events, list):
raise ApiError("Events not found")
for event in events:
if str(event.get("role_id")) == str(wanted_role_id):
return event.get("user_id")
raise ApiError(f"No shift today for role id {wanted_role_id}")


def task_title(plugin_slug, version):
return f"PSC для {plugin_slug} {version}"


def task_comment(plugin_slug, version):
repo = env("GITHUB_REPOSITORY")
download = f"https://downloads.wordpress.org/plugin/{plugin_slug}.{version}.zip"
lines = [
f"Релиз {plugin_slug} {version}.",
f"Архив: {download}",
]
if repo:
lines.append(f"Репозиторий: https://github.com/{repo}")
return "<br>".join(lines)


def summary(text):
print(text)
path = env("GITHUB_STEP_SUMMARY")
if path:
with open(path, "a", encoding="utf-8") as handle:
handle.write(text + "\n")


def create_task(session_id, user_id, title, comment):
project_id = require("DOBOARD_PROJECT_ID")
track_id = require("DOBOARD_TRACK_ID")
due = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
created = post(
company_url("task_add"),
{
"session_id": session_id,
"name": title,
"user_id": user_id,
"project_id": project_id,
"track_id": track_id,
"due_date": due,
},
)
task_id = (created.get("data") or {}).get("task_id")
if not task_id:
raise ApiError(f"Task add failed: {json.dumps(created, ensure_ascii=False)}")
commented = post(
company_url("comment_add"),
{
"session_id": session_id,
"task_id": task_id,
"comment": comment,
"project_id": project_id,
},
)
if not (commented.get("data") or {}).get("comment_id"):
raise ApiError(f"Comment add failed: {json.dumps(commented, ensure_ascii=False)}")
return task_id


def main():
version = require("INPUT_VERSION").lstrip("v")
plugin_slug = require("INPUT_PLUGIN_SLUG")
role_name = env("INPUT_ROLE_NAME", ROLE_NAME_DEFAULT)
create = env("INPUT_CREATE_TASK", "false").lower() == "true"
project_id = require("DOBOARD_PROJECT_ID")
track_id = require("DOBOARD_TRACK_ID")

session_id = authorize()
wanted_role_id = role_id(session_id, role_name)
user_id = duty_user_id(session_id, wanted_role_id)
title = task_title(plugin_slug, version)
comment = task_comment(plugin_slug, version)

summary("## PSC task")
summary(f"- Role: {role_name} ({wanted_role_id})")
summary(f"- Assignee user id: {user_id}")
summary(f"- Project: {project_id}")
summary(f"- Track: {track_id}")
summary(f"- Title: {title}")
summary(f"- Create task: {str(create).lower()}")

if not create:
summary("- Task was not created.")
return 0

try:
task_id = create_task(session_id, user_id, title, comment)
except ApiError:
session_id = authorize()
task_id = create_task(session_id, user_id, title, comment)
company_id = env("DOBOARD_COMPANY_ID", "1")
summary(f"- Created task: https://app.doboard.com/{company_id}/task/{task_id}")
return 0


if __name__ == "__main__":
try:
raise SystemExit(main())
except ApiError as exc:
print(f"::error::{exc}", file=sys.stderr)
raise SystemExit(1)
51 changes: 51 additions & 0 deletions .github/actions/deploy-wordpress-svn/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Deploy WordPress SVN
description: Publish WordPress plugin to SVN from the master checkout
inputs:
version:
required: true
plugin_slug:
description: WordPress.org plugin slug
required: true
main_file:
description: Main plugin file with the Version header, relative to the repository root
required: true
ignore_file:
description: rsync exclude list used to build the release tree
required: false
default: .7zignore
dry_run:
required: true
svn_username:
required: true
svn_password:
required: true
svn_url:
required: true
matrix_server:
required: false
matrix_room:
required: false
matrix_token:
required: false
runs:
using: composite
steps:
- name: Install dependencies
shell: bash
run: sudo apt-get update && sudo apt-get install -y subversion unzip rsync python3 curl

- name: Run deploy script
shell: bash
env:
INPUT_VERSION: ${{ inputs.version }}
INPUT_PLUGIN_SLUG: ${{ inputs.plugin_slug }}
INPUT_MAIN_FILE: ${{ inputs.main_file }}
INPUT_IGNORE_FILE: ${{ inputs.ignore_file }}
INPUT_DRY_RUN: ${{ inputs.dry_run }}
INPUT_SVN_USERNAME: ${{ inputs.svn_username }}
INPUT_SVN_PASSWORD: ${{ inputs.svn_password }}
INPUT_SVN_URL: ${{ inputs.svn_url }}
INPUT_MATRIX_SERVER: ${{ inputs.matrix_server }}
INPUT_MATRIX_ROOM: ${{ inputs.matrix_room }}
INPUT_MATRIX_TOKEN: ${{ inputs.matrix_token }}
run: bash ${{ github.action_path }}/entrypoint.sh
Loading
Loading