

{"id":414,"date":"2025-07-25T16:00:45","date_gmt":"2025-07-25T08:00:45","guid":{"rendered":"https:\/\/6589jk.cn\/?p=414"},"modified":"2025-07-25T16:00:47","modified_gmt":"2025-07-25T08:00:47","slug":"gitea%e8%87%aa%e5%8a%a8%e5%88%a0%e9%99%a4%e5%9e%83%e5%9c%be%e7%94%a8%e6%88%b7-c%e8%84%9a%e6%9c%ac","status":"publish","type":"post","link":"https:\/\/6589jk.cn\/index.php\/2025\/07\/25\/gitea%e8%87%aa%e5%8a%a8%e5%88%a0%e9%99%a4%e5%9e%83%e5%9c%be%e7%94%a8%e6%88%b7-c%e8%84%9a%e6%9c%ac\/","title":{"rendered":"gitea\u81ea\u52a8\u5220\u9664\u5783\u573e\u7528\u6237 C#\u811a\u672c"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>using System;\nusing System.Net.Http;\nusing System.Net.Http.Headers;\nusing System.Text.Json;\nusing System.Threading.Tasks;\n\n\nstring giteaUrl = \"https:\/\/&lt;Gitea>\/\"; \/\/ \u8bf7\u66ff\u6362\u4e3a Gitea \u670d\u52a1\u5668\u5730\u5740\nstring apiToken = \"&lt;apiToken>\"; \/\/ \u8bf7\u66ff\u6362\u4e3a\u4f60\u7684 API Token\nstring&#91;] NotDeleteUser = &#91;\"6589jk\", \"wh\"];\nHttpClient client = new HttpClient();\nclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(\"token\", apiToken);\n\nvar usersResponse = await client.GetAsync($\"{giteaUrl}\/api\/v1\/admin\/users\");\nif (usersResponse.IsSuccessStatusCode)\n{\n    var usersJson = await usersResponse.Content.ReadAsStringAsync();\n    var users = JsonSerializer.Deserialize&lt;User&#91;]>(usersJson);\n    await Parallel.ForEachAsync(users, new ParallelOptions\n    {\n        MaxDegreeOfParallelism = 4 \/\/ \u6700\u591a\u540c\u65f6\u5e76\u53d1 4 \u4e2a\u4efb\u52a1\n    }, async (user, _) =>\n    {\n        var username = user.username;\n        if (!NotDeleteUser.Contains(username))\n        {\n            \/\/Console.WriteLine($\"\u6b63\u5728\u5904\u7406\u7528\u6237\uff1a{username}\");\n\n            await DeleteUserRepositories(username);\n\n            var deleteUserResponse = await client.DeleteAsync($\"{giteaUrl}\/api\/v1\/admin\/users\/{username}\");\n            if (deleteUserResponse.StatusCode == System.Net.HttpStatusCode.NoContent)\n            {\n                Console.WriteLine($\"\u2705 \u7528\u6237 {username} \u5220\u9664\u6210\u529f\u3002\");\n            }\n            else\n            {\n                Console.WriteLine($\"\u274c \u5220\u9664\u7528\u6237 {username} \u5931\u8d25\u3002\u72b6\u6001\u7801\uff1a{deleteUserResponse.StatusCode}\");\n            }\n        }\n        else\n        {\n            \/\/Console.WriteLine($\"\u4fdd\u7559\u7528\u6237\uff1a{username}\");\n        }\n    });\n}\nelse\n{\n    Console.WriteLine($\"\u274c \u83b7\u53d6\u7528\u6237\u5217\u8868\u5931\u8d25\u3002\u72b6\u6001\u7801\uff1a{usersResponse.StatusCode}\");\n}\nasync Task DeleteUserRepositories(string username)\n{\n    var reposResponse = await client.GetAsync($\"{giteaUrl}\/api\/v1\/users\/{username}\/repos\");\n    if (reposResponse.IsSuccessStatusCode)\n    {\n        var reposJson = await reposResponse.Content.ReadAsStringAsync();\n        var repos = JsonSerializer.Deserialize&lt;Repository&#91;]>(reposJson);\n\n        foreach (var repo in repos)\n        {\n            var repoName = repo.name;\n            var deleteRepoResponse = await client.DeleteAsync($\"{giteaUrl}\/api\/v1\/repos\/{username}\/{repoName}\");\n            if (deleteRepoResponse.StatusCode == System.Net.HttpStatusCode.NoContent)\n            {\n                Console.WriteLine($\"\u2705 \u4ed3\u5e93 {repoName} \u5220\u9664\u6210\u529f\u3002\");\n            }\n            else\n            {\n                Console.WriteLine($\"\u274c \u5220\u9664\u4ed3\u5e93 {repoName} \u5931\u8d25\u3002\u72b6\u6001\u7801\uff1a{deleteRepoResponse.StatusCode}\");\n            }\n        }\n    }\n    else\n    {\n        Console.WriteLine($\"\u274c \u83b7\u53d6\u7528\u6237 {username} \u7684\u4ed3\u5e93\u5931\u8d25\u3002\u72b6\u6001\u7801\uff1a{reposResponse.StatusCode}\");\n    }\n}\n\npublic class User\n{\n    public string username { get; set; }\n}\n\npublic class Repository\n{\n    public string name { get; set; }\n}\n\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-414","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/posts\/414","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/comments?post=414"}],"version-history":[{"count":1,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/posts\/414\/revisions"}],"predecessor-version":[{"id":415,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/posts\/414\/revisions\/415"}],"wp:attachment":[{"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/media?parent=414"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/categories?post=414"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/tags?post=414"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}