Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: CI

on:
pull_request:
push:
branches:
- master

permissions:
contents: read

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version: 1.27.x
- name: Install cargo-make
run: cargo install --locked cargo-make --version 0.37.24
- name: Check
run: makers check
26 changes: 26 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Release

on:
push:
tags:
- v*

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-go@v7
with:
go-version: 1.27.x
- uses: goreleaser/goreleaser-action@v7
with:
version: v2.18.2
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ vendor/
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

dist/

# vscode
.vscode/
27 changes: 27 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: 2
project_name: synr

builds:
- main: ./cmd/synr
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64

archives:
- formats:
- tar.gz

checksum:
algorithm: sha256

changelog:
filters:
exclude:
- "^docs:"
- "^test:"
- "^chore:"
2 changes: 2 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[tools]
go = "1.27.1"
13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
repos:
- repo: local
hooks:
- id: makers-fmt-check
name: makers fmt-check
entry: makers fmt-check
language: system
pass_filenames: false
- id: makers-check
name: makers check
entry: makers check
language: system
pass_filenames: false
14 changes: 0 additions & 14 deletions .travis.yml

This file was deleted.

81 changes: 81 additions & 0 deletions Makefile.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
[tasks.fmt]
command = "go"
args = ["fmt", "./..."]

[tasks.fmt-check]
script = '''
files="$(gofmt -l $(git ls-files '*.go'))"
test -z "$files" || { echo "$files"; exit 1; }
'''

[tasks.vet]
command = "go"
args = ["vet", "./..."]

[tasks.test]
command = "go"
args = ["test", "-race", "./..."]

[tasks.test-config]
command = "go"
args = ["test", "./internal/adapter/config", "-v"]

[tasks.test-chatwork]
command = "go"
args = ["test", "./internal/adapter/chatwork", "-v"]

[tasks.test-zulip]
command = "go"
args = ["test", "./internal/adapter/zulip", "-v"]

[tasks.test-slack]
command = "go"
args = ["test", "./internal/adapter/slack", "-v"]

[tasks.test-cli]
command = "go"
args = ["test", "./internal/presentation/cli", "-v"]

[tasks.cli-help]
command = "go"
args = ["run", "./cmd/synr", "--help"]

[tasks.tidy]
command = "go"
args = ["mod", "tidy"]

[tasks.modules]
command = "go"
args = ["list", "-m", "all"]

[tasks.clean-testcache]
command = "go"
args = ["clean", "-testcache"]

[tasks.test-preview-repeat]
command = "go"
args = ["test", "./internal/presentation/cli", "./internal/usecase", "-run", "Preview|DoesNotLeave|ListFails", "-count=20"]

[tasks.build]
command = "go"
args = ["build", "./..."]

[tasks.vuln]
command = "go"
args = ["run", "golang.org/x/vuln/cmd/[email protected]", "./..."]

[tasks.goreleaser-check]
script = '''
git_common_dir="$(git rev-parse --git-common-dir)"
docker run --rm -v "$PWD:/src" -v "$git_common_dir:$git_common_dir:ro" -w /src goreleaser/goreleaser:v2.18.2 check
'''

[tasks.goreleaser-snapshot]
script = '''
git_common_dir="$(git rev-parse --git-common-dir)"
docker run --rm -v "$PWD:/src" -v "$git_common_dir:$git_common_dir:ro" -w /src goreleaser/goreleaser:v2.18.2 release --snapshot --clean
'''

[tasks.check]
dependencies = ["fmt-check", "vet", "test", "build", "vuln"]
command = "true"
108 changes: 81 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,97 @@
# synr: A script that leaving from your unnecessary chat rooms
[![Build Status](https://travis-ci.com/chck/synr.svg?branch=master)](https://travis-ci.com/chck/synr)
[![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/chck/synr/blob/master/LICENSE)
# synr

`synr` previews, and with explicit approval leaves, inactive conversations in
Slack, Chatwork, and Zulip.

## Requirements

Install the published command with Go:

```bash
go==1.12.*
go install github.com/chck/synr/cmd/synr@latest
```

## Installation
Source builds require Go 1.27. The repository checks are available through
`makers check`.

## Configuration

Credentials are read only from environment variables. Set the variables for the
one service you intend to scan:

```bash
% go get -u github.com/chck/synr
# Slack
export SYNR_SLACK_TOKEN=...

# Chatwork
export SYNR_CHATWORK_TOKEN=...

# Zulip
export SYNR_ZULIP_URL=https://zulip.example
export [email protected]
export SYNR_ZULIP_API_KEY=...
```

## Setup
```bash
# Set tokens in config/secrets.yaml
# slack: https://api.slack.com/docs/oauth-test-tokens
# chatwork: http://developer.chatwork.com/ja/authenticate.html
vi config/secrets.yaml
---
tokens:
chatwork: YOUR_CHARWORK_TOKEN
slack: YOUR_SLACK_TOKEN
Optional, non-secret protected conversation IDs are read from
`${XDG_CONFIG_HOME:-$HOME/.config}/synr/config.yaml`. Its schema is exactly:

```yaml
services:
slack:
protected_channels:
- C0123456789
chatwork:
protected_channels:
- "123456789"
zulip:
protected_channels:
- "42"
```

Unknown keys and malformed values are configuration errors. Conversation IDs
remain strings even when a service uses numeric IDs. The configuration file is
optional; `synr` never writes secrets to disk.

## Safety rules

`synr` is preview-only unless `--apply` is provided. A preview lists every
conversation with its service, name, stable ID, last activity, decision, and
reason. Only conversations with known activity strictly older than the cutoff
can be eligible.

- Slack: activity includes messages and thread replies across all accessible
history pages, and the workspace general channel is never left. The token
needs the applicable `channels:history` and `groups:history` scopes;
unavailable history stops the scan before any leave.
- Chatwork: sticky rooms, direct chats, and My Chat are never left. Only group
rooms can be eligible; unknown room types stop the scan before any leave.
- Zulip: channels pinned by the current user are never unsubscribed.
- Every service also preserves IDs listed in `protected_channels`.

## Usage
```bash
# Show usage with options
% synr help

# Dry-run
% synr -c slack -d
Preview Slack conversations inactive for more than three months:

# Run
% synr -c slack
```bash
synr scan --service slack --before-months 3
```

# Run with selected months elapsed from last update (default: 1)
% synr -c slack -m 3
After reviewing that preview, explicitly apply its eligible results:

# Supported chats are slack and chatwork
% synr -c chatwork -m 3
```bash
synr scan --service slack --before-months 3 --apply
```

`--service` accepts `slack`, `chatwork`, or `zulip`. `--before-months` defaults
to `1` and must be a positive integer.

## Manual checklist

1. Set credentials only for the intended service and add every conversation
that must be retained to `protected_channels`.
2. Run a preview without `--apply` and review every eligible row, including its
stable ID and inactivity reason.
3. Deliberately select the live apply scope only after that review; if needed,
protect all other conversations before continuing.
4. Run the matching command once with `--apply` and verify the resulting
service state.
Loading
Loading