11const { Octokit } = require ( "@octokit/rest" ) ;
2- const { writeFileSync } = require ( "fs" ) ;
3- const github = require ( "@actions/github" ) ;
42const core = require ( "@actions/core" ) ;
53
64async function run ( ) {
75 try {
86 const token = core . getInput ( 'token' ) ;
97 const repository = core . getInput ( 'repository' ) ;
10- const isReadmeUpdate = core . getInput ( 'isReadmeUpdate' ) ;
8+ const isReadmeUpdate = core . getInput ( 'isReadmeUpdate' ) === 'true' ;
119 const safeUserList = core . getInput ( 'safeUserList' ) . split ( "," ) ;
1210
13- const username = repository . split ( "/" ) [ 0 ] ;
14- const reponame = repository . split ( "/" ) [ 1 ] ;
11+ const [ username , reponame ] = repository . split ( "/" ) ;
1512 const octokit = new Octokit ( { auth : `token ${ token } ` } ) ;
1613
17- async function queryFollowers ( page = 1 ) {
18- let { data : followers } = await octokit . users . listFollowersForUser ( {
19- username,
20- per_page : 100 ,
21- page,
22- } ) ;
23- if ( followers . length >= 100 ) {
24- followers = followers . concat ( await queryFollowers ( page + 1 ) ) ;
25- }
26- return followers ;
27- }
14+ const followers = await fetchAllPages ( octokit . users . listFollowersForUser , { username } ) ;
15+ const following = await fetchAllPages ( octokit . users . listFollowingForUser , { username } ) ;
16+
17+ const unfollowers = following . filter ( user => ! followers . some ( follower => follower . login === user . login ) ) ;
18+ const unfollowing = followers . filter ( user => ! following . some ( follow => follow . login === user . login ) ) ;
2819
29- async function queryFollowing ( page = 1 ) {
30- let { data : following } = await octokit . users . listFollowingForUser ( {
31- username,
32- per_page : 100 ,
33- page,
34- } ) ;
35- if ( following . length >= 100 ) {
36- following = following . concat ( await queryFollowing ( page + 1 ) ) ;
37- }
38- return following ;
20+ if ( unfollowers . length > 0 ) {
21+ await processUsers ( unfollowers , octokit . users . unfollow , safeUserList ) ;
22+ console . log ( `You unfollowed ${ unfollowers . length } user(s).` ) ;
3923 }
4024
41- async function queryUnfollowUnfollowers ( unfollowers ) {
42- const unfollower = unfollowers . next ( ) ;
43- if ( ! unfollower . done ) {
44- const uusername = unfollower . value [ 1 ] . login ;
45- if ( ! safeUserList . includes ( username ) ) {
46- await octokit . users . unfollow ( { username : uusername } ) ;
47- }
48- await queryUnfollowUnfollowers ( unfollowers ) ;
49- }
50- return true ;
25+ if ( unfollowing . length > 0 ) {
26+ await processUsers ( unfollowing , octokit . users . follow ) ;
27+ console . log ( `You followed ${ unfollowing . length } user(s).` ) ;
5128 }
5229
53- async function queryFollowingUnfollowingUsers ( unfollowing , index = 0 ) {
54- const follower = unfollowing . next ( ) ;
55- if ( ! follower . done ) {
56- const uusername = follower . value [ 1 ] . login ;
57- await octokit . users . follow ( { username : uusername } ) ;
58- await queryFollowingUnfollowingUsers ( unfollowing ) ;
59- }
60- return true ;
30+ if ( isReadmeUpdate && ( unfollowers . length > 0 || unfollowing . length > 0 ) ) {
31+ await updateReadme ( octokit , username , reponame , followers ) ;
6132 }
6233
63- const { data : user } = await octokit . users . getByUsername ( {
64- username,
65- } ) ;
34+ console . log ( "Done!" ) ;
35+ } catch ( error ) {
36+ console . log ( error . message ) ;
37+ }
38+ }
6639
67- function dealBlog ( blog ) {
68- if ( blog ) {
69- return `[${ blog } ](https://${ blog } )` ;
70- }
71- return "-" ;
72- }
40+ async function fetchAllPages ( apiMethod , params , page = 1 , results = [ ] ) {
41+ const { data } = await apiMethod ( { ...params , per_page : 100 , page } ) ;
42+ results . push ( ...data ) ;
43+ return data . length === 100 ? fetchAllPages ( apiMethod , params , page + 1 , results ) : results ;
44+ }
7345
74- async function checkFileExistence ( ) {
75- try {
76- const { data : { sha } } = await octokit . repos . getReadme ( {
77- owner : username ,
78- repo : reponame ,
79- } ) ;
80- return {
81- status : true ,
82- message : sha
83- } ;
84- } catch ( error ) {
85- if ( error . status === 404 ) {
86- return {
87- status : false ,
88- message : "File does not exist."
89- } ;
90- } else {
91- return {
92- status : false ,
93- message : error
94- } ;
95- }
96- }
46+ async function processUsers ( users , apiMethod , safeUserList = [ ] ) {
47+ for ( const user of users ) {
48+ if ( ! safeUserList . includes ( user . login ) ) {
49+ await apiMethod ( { username : user . login } ) ;
9750 }
51+ }
52+ }
9853
99- const followers = await queryFollowers ( ) ;
100- const following = await queryFollowing ( ) ;
101- const unfollowers = following . filter ( user => ! followers . map ( follower => follower . login ) . includes ( user . login ) ) ;
102- const unfollowing = followers . filter ( user => ! following . map ( follow => follow . login ) . includes ( user . login ) ) ;
103- followers . reverse ( ) ;
104-
105- if ( unfollowers . length > 0 ) {
106- await queryUnfollowUnfollowers ( unfollowers . entries ( ) ) ;
107- console . log ( `You unfollowed the ${ unfollowers . length } bad guy${ unfollowers . length > 1 ? 's' : '' } .` ) ;
108- }
109- if ( unfollowing . length > 0 ) {
110- await queryFollowingUnfollowingUsers ( unfollowing . entries ( ) ) ;
111- console . log ( `You followed the ${ unfollowing . length } good guy${ unfollowing . length > 1 ? 's' : '' } .` ) ;
112- }
54+ async function updateReadme ( octokit , username , reponame , followers ) {
55+ const { data : user } = await octokit . users . getByUsername ( { username } ) ;
56+ const content = generateReadmeContent ( user , followers ) ;
57+ const { status, message : sha } = await checkFileExistence ( octokit , username , reponame ) ;
58+
59+ const requestData = {
60+ owner : username ,
61+ repo : reponame ,
62+ path : "README.md" ,
63+ message : "Updated: Readme.md With New Infos By Github Action" ,
64+ content : Buffer . from ( content ) . toString ( 'base64' ) ,
65+ committer : { name : username , email : `${ username } @users.noreply.github.com` } ,
66+ author : { name : username , email : `${ username } @users.noreply.github.com` } ,
67+ ...( status && { sha } )
68+ } ;
69+
70+ await octokit . repos . createOrUpdateFileContents ( requestData ) ;
71+ }
72+
73+ async function checkFileExistence ( octokit , owner , repo ) {
74+ try {
75+ const { data : { sha } } = await octokit . repos . getReadme ( { owner, repo } ) ;
76+ return { status : true , message : sha } ;
77+ } catch ( error ) {
78+ return { status : false , message : error . status === 404 ? "File does not exist." : error . message } ;
79+ }
80+ }
11381
114- if ( isReadmeUpdate ) {
115- if ( unfollowers . length > 0 || unfollowing . length > 0 ) {
116- const content = `## ${ username }
82+ function generateReadmeContent ( user , followers ) {
83+ return `## ${ user . login }
11784<img src="${ user . avatar_url } " width="150" />
11885
11986| Name | Bio | Blog | Location | Company |
12087| -- | -- | -- | -- | -- |
121- | ${ user . name || "-" } | ${ user . bio || "-" } | ${ dealBlog ( user . blog ) } | ${
122- user . location || "-"
123- } | ${ getCompany ( user . company ) } |
88+ | ${ user . name || "-" } | ${ user . bio || "-" } | ${ formatBlog ( user . blog ) } | ${ user . location || "-" } | ${ formatCompany ( user . company ) } |
12489
12590## Followers <kbd>${ followers . length } </kbd>
12691
@@ -129,90 +94,25 @@ async function run() {
12994</table>
13095
13196## LICENSE
132- Copyright (c) 2023-present [Huniko519 ](https://github.com/Huniko519 )
97+ Copyright (c) 2023-present [${ user . login } ](https://github.com/${ user . login } )
13398` ;
134-
135- let requestData = {
136- owner : username ,
137- repo : reponame ,
138- path : "README.md" ,
139- message : "Updated: Readme.md With New Infos By Github Action" ,
140- content : Buffer . from ( content ) . toString ( 'base64' ) ,
141- committer : {
142- name : username ,
143- email : `${ username } @users.noreply.github.com`
144- } ,
145- author : {
146- name : username ,
147- email : `${ username } @users.noreply.github.com`
148- } ,
149- }
150- const shainfo = await checkFileExistence ( ) ;
151- if ( shainfo . status ) {
152- requestData [ "sha" ] = shainfo . message ;
153- }
154- await octokit . repos . createOrUpdateFileContents ( requestData ) ;
155- }
156- }
157-
158- console . log ( "Done!" ) ;
159- } catch ( error ) {
160- console . log ( error . message ) ;
161- }
16299}
163100
164- function formatTable ( arr ) {
165- if ( arr . length === 0 ) {
166- return "" ;
167- }
168- let result = "" ;
169- let row = arr . length / 10 ;
170- const lastNo = arr . length % 10 ;
171- if ( lastNo != 0 ) row += 1 ;
172- for ( let j = 1 ; j <= row ; j += 1 ) {
173- let data = "" ;
174- data = `<tr width="100%">
175- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 ] ) }
176- </td>
177- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 1 ] ) }
178- </td>
179- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 2 ] ) }
180- </td>
181- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 3 ] ) }
182- </td>
183- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 4 ] ) }
184- </td>
185- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 5 ] ) }
186- </td>
187- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 6 ] ) }
188- </td>
189- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 7 ] ) }
190- </td>
191- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 8 ] ) }
192- </td>
193- <td width="10%" align="center">${ getUser ( arr [ ( j - 1 ) * 10 + 9 ] ) }
194- </td>
195- </tr>` ;
196- result += data ;
197- }
198- return result ;
101+ function formatBlog ( blog ) {
102+ return blog ? `[${ blog } ](https://${ blog } )` : "-" ;
199103}
200104
201- function getUser ( user ) {
202- return user
203- ? `
204- <a href="${ user . html_url } ">
205- <img src="${ user . avatar_url } " />
206- </a>`
207- : "" ;
105+ function formatCompany ( company ) {
106+ return company ? `[@${ company . replace ( "@" , "" ) } ](https://github.com/${ company . replace ( "@" , "" ) } )` : "-" ;
208107}
209108
210- function getCompany ( c ) {
211- if ( c ) {
212- c = c . replace ( "@" , "" ) ;
213- return `[@${ c } ](https://github.com/${ c } )` ;
214- }
215- return `-` ;
109+ function formatTable ( users ) {
110+ return users . reduce ( ( acc , user , index ) => {
111+ if ( index % 10 === 0 ) acc += "<tr width='100%'>" ;
112+ acc += `<td width='10%' align='center'><a href='${ user . html_url } '><img src='${ user . avatar_url } ' /></a></td>` ;
113+ if ( index % 10 === 9 ) acc += "</tr>" ;
114+ return acc ;
115+ } , "" ) ;
216116}
217117
218118run ( ) ;
0 commit comments