Support to export blocks/mutes as CSV files (#626)

This commit is contained in:
TAKAHASHI Shuuji 2023-08-08 00:16:52 +09:00 committed by GitHub
parent 4a9109271d
commit 67d755e6d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 136 additions and 3 deletions

View File

@ -65,6 +65,16 @@ urlpatterns = [
settings.CsvFollowers.as_view(), settings.CsvFollowers.as_view(),
name="settings_export_followers_csv", name="settings_export_followers_csv",
), ),
path(
"@<handle>/settings/import_export/blocks.csv",
settings.CsvBlocks.as_view(),
name="settings_export_blocks_csv",
),
path(
"@<handle>/settings/import_export/mutes.csv",
settings.CsvMutes.as_view(),
name="settings_export_mutes_csv",
),
path( path(
"@<handle>/settings/migrate_in/", "@<handle>/settings/migrate_in/",
settings.MigrateInPage.as_view(), settings.MigrateInPage.as_view(),

View File

@ -50,7 +50,7 @@
<small>{{ numbers.blocks }} {{ numbers.blocks|pluralize:"people,people" }}</small> <small>{{ numbers.blocks }} {{ numbers.blocks|pluralize:"people,people" }}</small>
</td> </td>
<td> <td>
<a href="{% url "settings_export_blocks_csv" handle=identity.handle %}">Download CSV</a>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -59,7 +59,7 @@
<small>{{ numbers.mutes }} {{ numbers.mutes|pluralize:"people,people" }}</small> <small>{{ numbers.mutes }} {{ numbers.mutes|pluralize:"people,people" }}</small>
</td> </td>
<td> <td>
<a href="{% url "settings_export_mutes_csv" handle=identity.handle %}">Download CSV</a>
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -88,3 +88,92 @@ def test_export_followers(
) )
assert response.status_code == 200 assert response.status_code == 200
assert response.content.strip() == b"Account address\r\ntest@example2.com" assert response.content.strip() == b"Account address\r\ntest@example2.com"
@pytest.mark.django_db
def test_export_blocks(
client_with_user: Client,
identity: Identity,
identity2: Identity,
stator: StatorRunner,
httpx_mock: HTTPXMock,
):
"""
Validates the "export a CSV of blocked users" functionality works
"""
# Block remote_identity
IdentityService(identity).block(identity2)
# Run stator to process it
stator.run_single_cycle()
# Download the CSV
response = client_with_user.get(
f"/@{identity.handle}/settings/import_export/blocks.csv"
)
assert response.status_code == 200
assert response.content.strip() == b"Account address\r\ntest@example2.com"
# Unblock should clear the CSV content
IdentityService(identity).unblock(identity2)
# Run stator to process it
stator.run_single_cycle()
response = client_with_user.get(
f"/@{identity.handle}/settings/import_export/blocks.csv"
)
assert response.status_code == 200
assert response.content.strip() == b"Account address"
@pytest.mark.django_db
def test_export_mutes(
client_with_user: Client,
identity: Identity,
identity2: Identity,
stator: StatorRunner,
httpx_mock: HTTPXMock,
):
"""
Validates the "export a CSV of muted users" functionality works
"""
# Mute remote_identity
IdentityService(identity).mute(identity2)
# Run stator to process it
stator.run_single_cycle()
# Download the CSV
response = client_with_user.get(
f"/@{identity.handle}/settings/import_export/mutes.csv"
)
assert response.status_code == 200
assert (
response.content.strip()
== b"Account address,Hide notifications\r\ntest@example2.com,false"
)
# Mute remote_identity
IdentityService(identity).mute(identity2, include_notifications=True)
# Run stator to process it
stator.run_single_cycle()
# Download the CSV
response = client_with_user.get(
f"/@{identity.handle}/settings/import_export/mutes.csv"
)
assert response.status_code == 200
assert (
response.content.strip()
== b"Account address,Hide notifications\r\ntest@example2.com,true"
)
# Unmute should clear the CSV content
IdentityService(identity).unmute(identity2)
response = client_with_user.get(
f"/@{identity.handle}/settings/import_export/mutes.csv"
)
assert response.status_code == 200
assert response.content.strip() == b"Account address,Hide notifications"

View File

@ -6,8 +6,10 @@ from django.views.generic import View
from users.views.settings.delete import DeleteIdentity # noqa from users.views.settings.delete import DeleteIdentity # noqa
from users.views.settings.follows import FollowsPage # noqa from users.views.settings.follows import FollowsPage # noqa
from users.views.settings.import_export import ( # noqa from users.views.settings.import_export import ( # noqa
CsvBlocks,
CsvFollowers, CsvFollowers,
CsvFollowing, CsvFollowing,
CsvMutes,
ImportExportPage, ImportExportPage,
) )
from users.views.settings.interface import InterfacePage # noqa from users.views.settings.interface import InterfacePage # noqa

View File

@ -7,7 +7,7 @@ from django.shortcuts import redirect
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.generic import FormView, View from django.views.generic import FormView, View
from users.models import Follow, InboxMessage from users.models import Block, Follow, InboxMessage
from users.views.base import IdentityViewMixin from users.views.base import IdentityViewMixin
@ -147,3 +147,35 @@ class CsvFollowers(CsvView):
def get_handle(self, follow: Follow): def get_handle(self, follow: Follow):
return follow.source.handle return follow.source.handle
class CsvBlocks(CsvView):
columns = {
"Account address": "get_handle",
}
filename = "blocked_accounts.csv"
def get_queryset(self, request):
return self.identity.outbound_blocks.active().filter(mute=False)
def get_handle(self, block: Block):
return block.target.handle
class CsvMutes(CsvView):
columns = {
"Account address": "get_handle",
"Hide notifications": "get_notification",
}
filename = "muted_accounts.csv"
def get_queryset(self, request):
return self.identity.outbound_blocks.active().filter(mute=True)
def get_handle(self, mute: Block):
return mute.target.handle
def get_notification(self, mute: Block):
return mute.include_notifications