Completed
Push — master ( c382ba...14c837 )
by Sepand
27s
created

follow()   B

Complexity

Conditions 5

Size

Total Lines 17

Duplication

Lines 17
Ratio 100 %

Importance

Changes 6
Bugs 5 Features 3
Metric Value
cc 5
c 6
b 5
f 3
dl 17
loc 17
rs 8.5454
1
# -*- coding: utf-8 -*-
2
import requests
3
import sys
4
import socket
5
import os
6
import datetime
7
from functools import reduce
8
import time
9
from random import randint
10
import sys
11
from art import tprint
12
DEBUG=False
13
import gc
14
15
16
def zero_insert(input_string):
17
    '''
18
    This function get a string as input if input is one digit add a zero
19
    :param input_string: input digit az string
20
    :type input_string:str
21
    :return: modified output as str
22
    '''
23
    if len(input_string)==1:
24
        return "0"+input_string
25
    return input_string
26
27
def time_convert(input_string):
28
    '''
29
    This function convert input_string from uptime from sec to DD,HH,MM,SS Format
30
    :param input_string: input time string  in sec
31
    :type input_string:str
32
    :return: converted time as string
33
    '''
34
    input_sec=float(input_string)
35
    input_minute=input_sec//60
36
    input_sec=int(input_sec-input_minute*60)
37
    input_hour=input_minute//60
38
    input_minute=int(input_minute-input_hour*60)
39
    input_day=int(input_hour//24)
40
    input_hour=int(input_hour-input_day*24)
41
    return zero_insert(str(input_day))+" days, "+zero_insert(str(input_hour))+" hour, "+zero_insert(str(input_minute))+" minutes, "+zero_insert(str(input_sec))+" seconds"
42
43
def url_maker_following(Name,page_number):
44
    '''
45
    This function return github following page url
46
    :param Name: Username
47
    :param page_number: page nubmer of following page
48
    :type Name:str
49
    :type Page:int
50
    :return: github following url as string
51
    '''
52
    return "https://github.com/"+Name+"?page="+str(page_number)+"&tab=following"
53
54
def url_maker_repo(Name,page_number):
55
    '''
56
    This function return github repo page url
57
    :param Name: Username
58
    :param page_number: page nubmer of repos page
59
    :type Name:str
60
    :type Page:int
61
    :return: github repos url as string
62
    '''
63
    return "https://github.com/"+Name+"?page="+str(page_number)+"&tab=repositories"
64
def url_maker_follower(Name,page_number):
65
    '''
66
    This function return github follower page url
67
    :param Name: username
68
    :param page_number: page number of follower page
69
    :type Name:str
70
    :type page_number:int
71
    :return: github follower url as string
72
    '''
73
    return "https://github.com/" + Name + "?page=" + str(page_number) + "&tab=followers"
74
def url_maker_star(Name,page_number):
75
    '''
76
    This function return github stars page url
77
    :param Name: username
78
    :param page_number: page number of stars
79
    :type Name :str
80
    :type page_number:int
81 View Code Duplication
    :return: github star url as string
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
82
    '''
83
    return "https://github.com/"+Name+"?page="+str(page_number)+"&tab=stars"
84
def repo_extract(input_string,username):
85
    '''
86
    This function extract repo from raw_html
87
    :param input_string: raw input html
88
    :param user_name: user_name
89
    :type input_string:str
90
    :type user_name:str
91
    :return: repo_list as list
92
    '''
93
    try:
94
        user_list=[]
95
        index=0
96
        shift=len(username)+1
97
        while(index!=-1):
98
            index=input_string.find('src="/'+username,index+shift,len(input_string))
99
            length=input_string[index:].find('graphs/')
100
            star_repo=input_string[index+5:index+length]
101
            if star_repo.find("<svg")==-1 and len(star_repo)!=0:
102
                user_list.append(star_repo)
103
        return user_list
104 View Code Duplication
    except Exception as ex:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
105
        pass
106
107
def star_extract(input_string):
108
    '''
109
    This function extract stared repo from raw_html
110
    :param input_string: raw input html
111
    :param follower_name: follower_name
112
    :type input_string:str
113
    :type follower_name:str
114
    :return: user_list as list
115
    '''
116
    user_list=[]
117
    index=0
118
    try:
119
        while(index!=-1):
120
            index=input_string.find('<a class="muted-link mr-3',index+33,len(input_string))
121
            length=input_string[index+33:].find('stargazers">\n')
122
            star_repo=input_string[index+34:index+33+length]
123
            if star_repo.find("<svg")==-1 and len(star_repo)!=0:
124
                user_list.append(star_repo)
125
        return user_list
126
    except Exception as ex:
127
        pass
128
def org_list_gen(name):
129
    url=url_maker_follower(name,1)
130
    raw_data=get_html(url)
131
    org_index = raw_data.find("col-9 float-left pl-2")
132
    org_data = raw_data[:org_index]
133
    index=0
134
    org_list=[]
135
    while (index != -1):
136
        index = org_data.find('alt="@', index + 6, len(org_data))
137
        length = org_data[index + 6:].find('"')
138
        org_name = org_data[index + 6:index + 6 + length]
139
        if org_name != name:
140
            org_list.append(org_name)
141
    return org_list[:-1]
142
def user_list_gen(input_string,follower_name):
143
    '''
144
    This function extract usernames from raw_html
145
    :param input_string: raw input html
146
    :param follower_name: follower_name
147
    :type input_string:str
148
    :type follower_name:str
149
    :return: user_list as list
150
    '''
151
    try:
152
        user_list = []
153
        index = 0
154
        org_index=input_string.find("col-9 float-left pl-2")
155
        repo_data=input_string[org_index:]
156
        while(index!=-1):
157
            index=repo_data.find('alt="@',index+6,len(input_string))
158
            length=repo_data[index+6:].find('"')
159
            user_name=repo_data[index+6:index+6+length]
160
            if user_name!=follower_name:
161
                user_list.append(user_name)
162
        return user_list[:-1]
163
    except Exception as ex:
164
        pass
165
def get_html(url):
166
    '''
167
    This function extract raw_html file
168
    :param url: url
169
    :type url:str
170
    :return: html data
171
    '''
172
    time.sleep(create_random_sleep())
173
    if internet()==True:
174
        new_session=requests.session()
175
        new_session.cookies.clear()
176
        raw_html=new_session.get(url)
177
        new_session.close()
178
        raw_data=raw_html.text
179
        if "Not Found" in raw_data:
180
            print("Invalid Github User")
181
            sys.exit()
182 View Code Duplication
        return raw_data
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
183
    else:
184
        print("Error In Internet")
185
        pass
186
187
188
def end_check(input_string):
189
    '''
190
    This function check end page
191
    :param input_string: raw html
192
    :type input_string:str
193
    :return: True or False
194
    '''
195
    if input_string.find("reached the end")!=-1:
196
        return True
197
    else:
198
        return False
199
def follower_list_gen(follower_name,page_number=0,counter=0):
200
    '''
201
    This function generate follower_list
202
    :param follower_name: username
203
    :type follower_name:str
204
    :return: username follower list
205
    '''
206
    try:
207
        follower_list = []
208
        while (True):
209
            page_number += 1
210
            follower_url = url_maker_follower(follower_name, page_number)
211
            follower_html = get_html(follower_url)
212
            if end_check(follower_html) == True:
213
                break
214
            temp_list = user_list_gen(follower_html,follower_name)
215
            follower_list.extend(temp_list)
216
        return follower_list
217
    except Exception as ex:
218
        if counter>3:
219
            sys.exit()
220
        error_log("Error In Page "+str(page_number)+" Follower Page")
221
        follower_list_gen(follower_name,page_number,counter+1)
222
def repo_list(username,page_number=0,counter=0):
223
    '''
224
    This function return stared_repo list
225
    :param username: username
226
    :type username:str
227
    :return: stared repo as list
228
    '''
229
    try:
230
        repo_list_temp=[]
231
        while (True):
232
            page_number += 1
233
            repo_url = url_maker_repo(username, page_number)
234
            repo_html = get_html(repo_url)
235
            temp_list = repo_extract(repo_html,username)
236
            if len(temp_list)==0:
237
                break
238
            repo_list_temp.extend(temp_list)
239
        return repo_list_temp
240
    except Exception as ex:
241
        if counter>3:
242
            sys.exit()
243
        error_log("Error In Page " + str(page_number) + " Repos Page")
244
        repo_list(username,page_number,counter+1)
245
def star_list(username,page_number=0,counter=0):
246
    '''
247
    This function return stared_repo list
248
    :param username: username
249
    :type username:str
250
    :return: stared repo as list
251
    '''
252 View Code Duplication
    try:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
253
        star_list_temp=[]
254
        while (True):
255
            page_number += 1
256
            star_url = url_maker_star(username, page_number)
257
            star_html = get_html(star_url)
258
            temp_list = star_extract(star_html)
259
            if len(temp_list)==0:
260
                break
261
            star_list_temp.extend(temp_list)
262
        return star_list_temp
263
    except Exception as ex:
264
        if counter>3:
265
            sys.exit()
266
        error_log("Error In Page " + str(page_number) + " Stars Page")
267
        star_list(username,page_number,counter+1)
268
269
def following_list_gen(follower_name,page_number=0,counter=0):
270
    '''
271
    This function generate following list
272
    :param follower_name: username
273
    :type follower_name:str
274
    :return: username following list
275
    '''
276
    try:
277
        following_list = []
278
        while (True):
279
            page_number+=1
280
            following_url = url_maker_following(follower_name, page_number)
281
            following_html = get_html(following_url)
282
            if end_check(following_html) == True:
283
                break
284
            temp_list = user_list_gen(following_html,follower_name)
285
            following_list.extend(temp_list)
286
        return following_list
287
    except Exception as ex:
288
        if counter>3:
289
            sys.exit()
290
        error_log("Error In Page " + str(page_number) + " Following Page")
291
        following_list_gen(follower_name,page_number,counter+1)
292
293
def error_log(msg):
294
    """
295
    Create the errorlog of the app
296
    :param msg: error message
297
    :type msg:str
298
    """
299
    if "log" not in os.listdir():
300
        os.mkdir("log")
301
    file = open(reduce(os.path.join, [os.getcwd(), "log", "error_log.txt"]), "a")
302
    file.write(str(datetime.datetime.now()) + " --> " + str(msg) + "\n")
303
    file.close()
304
305
def internet(host="8.8.8.8", port=53, timeout=10):
306
    """
307
    Check Internet Connections.
308
    :param  host: the host that check connection to
309
    :param  port: port that check connection with
310
    :param  timeout: times that check the connnection
311
    :type host:str
312
    :type port:int
313
    :type timeout:int
314
    :return bool: True if Connection is Stable
315
    >>> internet() # if there is stable internet connection
316
    True
317
    >>> internet() # if there is no stable internet connection
318
    False
319
    """
320
    try:
321
        socket.setdefaulttimeout(timeout)
322
        socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
323
        return True
324
    except Exception as ex:
325
        return False
326
327
def create_random_sleep(index=1,min_time=1,max_time=3):
328
    '''
329
    This function generate sleep time with random processes
330
    :param index: index to determine first page  and messages(index = 0 is for first page)
331
    :param min_time: minimum time of sleep
332
    :param max_time: maximum time of sleep
333
    :type index:int
334
    :type min_time:int
335
    :type max_time:int
336
    :return: time of sleep as integer (a number between max and min)
337
    '''
338
    if index==0:
339
        time_sleep = 5
340
        if DEBUG==True:
341
            print("Wait "+str(time_sleep)+" sec for first search . . .")
342
    else:
343
        time_sleep = randint(min_time, max_time)
344
        if DEBUG==True:
345
            print("Wait "+str(time_sleep)+" sec for next search . . .")
346
    if DEBUG==True:
347
        print_line(70,"*")
348
    return time_sleep
349
350
def print_line(number=30,char="-"):
351
    '''
352
    This function print line in screen
353
    :param number: number of items in each line
354
    :param char: each char of line
355
    :return: None
356
    '''
357
    line=""
358
    for i in range(number):
359
        line=line+char
360
    print(line)
361
362
363
def list_maker(username,keyword=["1"]):
364
    '''
365
    This function create following and follower list
366
    :param username: username
367
    :type username:str
368
    :return: (list_1,list_2) as tuple
369
    '''
370
    try:
371
        print("Collecting Follower Information ...")
372
        print_line(70, "*")
373
        list_1 = follower_list_gen(username)
374
        file = open(username + "_follower.log", "w")
375
        print(str(len(list_1)) + " Followers --> " + username + "_follower.log")
376
        print_line(70, "*")
377
        file.write("\n".join(list_1))
378
        file.close()
379
        print('Collecting Following Information ...')
380
        print_line(70, "*")
381
        list_2 = following_list_gen(username)
382
        file = open(username + "_following.log", "w")
383
        print(str(len(list_2)) + " Following --> " + username + "_following.log")
384
        print_line(70, "*")
385
        file.write("\n".join(list_2))
386
        file.close()
387
        if "1" in keyword:
388
            print('Collecting Stars Information ...')
389
            print_line(70, "*")
390
            stars=star_list(username)
391
            file = open(username + "_stars.log", "w")
392
            print(str(len(stars)) + " Stars --> " + username + "_stars.log")
393
            print_line(70, "*")
394
            file.write("\n".join(stars))
395
            file.close()
396
        if "2" in keyword:
397
            print('Collecting Repos Information ...')
398
            print_line(70, "*")
399
            repos = repo_list(username)
400
            file = open(username + "_repos.log", "w")
401
            print(str(len(repos)) + " Repos --> " + username + "_repos.log")
402
            print_line(70, "*")
403
            file.write("\n".join(repos))
404
            file.close()
405
        if "3" in keyword:
406
            print('Collecting Organizations Information ...')
407
            print_line(70, "*")
408
            orgs = org_list_gen(username)
409
            file = open(username + "_orgs.log", "w")
410
            print(str(len(orgs)) + " Organizations --> " + username + "_orgs.log")
411
            print_line(70, "*")
412
            file.write("\n".join(orgs))
413
            file.close()
414
        return (list_1,list_2)
415
    except Exception as ex:
416
        error_log(str(ex))
417
418
def dif(list_1,list_2,username):
419
    '''
420
    This function generate dif files
421
    :param list_1:follower list
422
    :param list_2: following list
423
    :type list_1:list
424
    :type list_2:list
425
    :return: None
426
    '''
427
    try:
428
        file = open(username + "_NotFollower.log", "w")
429
        dif_list_1 = list(set(list_2) - set(list_1))
430
        print(str(len(dif_list_1)) + " Following - Not Follower --> " + username + "_NotFollower.log")
431
        print_line(70, "*")
432
        file.write("\n".join(dif_list_1))
433
        file.close()
434
        file = open(username + "_NotFollowing.log", "w")
435
        dif_list_2 = list(set(list_1) - set(list_2))
436
        print(str(len(dif_list_2)) + " Follower - Not Following --> " + username + "_NotFollowing.log")
437
        print_line(70, "*")
438
        file.write("\n".join(dif_list_2))
439
        file.close()
440
        return [dif_list_1,dif_list_2]
441
    except Exception as ex:
442
        print(str(ex))
443 View Code Duplication
def unfollow(username,password,id_list):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
444
    for user in id_list:
445
        response=requests.delete("https://api.github.com/user/following/" + user, auth=(username, password))
446
        status_code=int(response.status_code)
447
        if status_code!=204:
448
            if status_code==401:
449
                print("[Error] Authentication Error")
450
                return False
451
            elif status_code==403:
452
                print("[Error] Maximum number of login attempts exceeded")
453
                sys.exit()
454
            else:
455
                print("[Error] in " + user + " unfollow!")
456
        else:
457
            print(user+" Unfollowed")
458
        time.sleep(3)
459
    return True
460 View Code Duplication
def follow(username,password,id_list):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
461
    for user in id_list:
462
        response = requests.put("https://api.github.com/user/following/" + user, auth=(username, password))
463
        status_code = int(response.status_code)
464
        if status_code!=204:
465
            if status_code==401:
466
                print("[Error] Authentication Error")
467
                return False
468
            elif status_code==403:
469
                print("[Error] Maximum number of login attempts exceeded")
470
                sys.exit()
471
            else:
472
                print("[Error] in "+user+" follow!")
473
        else:
474
            print(user+" Followed")
475
        time.sleep(3)
476
    return True
477
def get_input():
478
    tprint("git\nfollow")
479
    username = input("Please Enter Your Github Username : ")
480
    keys=input("1- Collecting Stars Information\n2- Collecting Repos Information\n3- Collecting Organizations Information (Enter Number Seperated By , )")
481
    keys=keys.split(",")
482
    return [username,keys]
483
def run():
484
    password = ""
485
    auth=False
486
    time_1 = time.perf_counter()
487
    [username,keys]=get_input()
488
    (list_1, list_2) = list_maker(username,keys)
489
    dif_lists = dif(list_1, list_2, username)
490
    time_2 = time.perf_counter()
491
    dif_time = str(time_2 - time_1)
492
    print("Data Generated In " + time_convert(dif_time) + " sec")
493
    print("Log Files Are Ready --> " + os.getcwd())
494
    if len(dif_lists[0])>0:
495
        input_data = input("Unfollow Non-follower?Yes[y],No[n] ")
496
        if input_data.upper() == "Y":
497
            while(auth==False):
498
                password = input("Please Enter Password : ")
499
                print("Processing ... ")
500
                auth=unfollow(username, password, dif_lists[0])
501
    if len(dif_lists[1])>0:
502
        input_data = input("Follow Non-following?Yes[y],No[n] ")
503
        if input_data.upper() == "Y":
504
            if auth==True:
505
                print("Processing ... ")
506
                auth= follow(username, password, dif_lists[1])
507
            while(auth==False):
508
                password = input("Please Enter Password : ")
509
                print("Processing ... ")
510
                auth=follow(username, password, dif_lists[1])
511
    exit_string=input("Exit [E] / Restart[R] ?")
512
    gc.collect()
513
    if exit_string.upper()=="E":
514
        sys.exit()
515
516
517
518
519
520
521
522
523
524
525
526
527
528