├── LICENSE ├── README.md ├── accounts ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── admin.cpython-36.pyc │ ├── forms.cpython-36.pyc │ ├── models.cpython-36.pyc │ ├── urls.cpython-36.pyc │ └── views.cpython-36.pyc ├── admin.py ├── api │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── permissions.cpython-36.pyc │ │ ├── serializers.cpython-36.pyc │ │ ├── urls.cpython-36.pyc │ │ ├── utils.cpython-36.pyc │ │ └── views.cpython-36.pyc │ ├── permissions.py │ ├── serializers.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20191127_1345.py │ ├── 0003_myuser_spam_count.py │ ├── 0004_auto_20191127_2121.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-36.pyc │ │ ├── 0002_auto_20191127_1345.cpython-36.pyc │ │ ├── 0003_myuser_spam_count.cpython-36.pyc │ │ ├── 0004_auto_20191127_2121.cpython-36.pyc │ │ └── __init__.cpython-36.pyc ├── models.py ├── tests.py ├── urls.py └── views.py ├── data ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── admin.cpython-36.pyc │ ├── models.cpython-36.pyc │ ├── urls.cpython-36.pyc │ └── views.cpython-36.pyc ├── admin.py ├── api │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── serializers.cpython-36.pyc │ │ ├── urls.cpython-36.pyc │ │ └── views.cpython-36.pyc │ ├── serializers.py │ ├── urls.py │ └── views.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20191127_2150.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-36.pyc │ │ ├── 0002_auto_20191127_2150.cpython-36.pyc │ │ └── __init__.cpython-36.pyc ├── models.py ├── templates │ └── home.html ├── tests.py ├── urls.py └── views.py ├── db.sqlite3 ├── manage.py ├── requirements.txt └── truecaller ├── __init__.py ├── __pycache__ ├── __init__.cpython-36.pyc ├── putdata.cpython-36.pyc ├── settings.cpython-36.pyc ├── urls.cpython-36.pyc └── wsgi.cpython-36.pyc ├── data.csv ├── putdata.py ├── restconf ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ └── main.cpython-36.pyc └── main.py ├── settings.py ├── urls.py └── wsgi.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Naveen Arora 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Truecaller-APIs 2 | 3 | This is a brief description of what this app does and how these apis work
4 | As specified, this app is just like truecaller and works on same principle
5 | 6 | To start the project, one needs to run the server first using the specified virtual environment.
7 | On Linux,
8 | Enter following commands once you are in this directory
9 |
10 |     source venv/bin/activate 
11 |     cd truecaller
12 |     python manage.py runserver
13 | 
14 | Now the application server has started,

15 | 16 |

Every Functionality implemented in the code could have been implemented using various other methods. I have used methods which I felt would be appropriate

17 | To access anything in the api , one needs to be logged in otherwise it will raise Authentication errors.

18 | 19 |

To register using the API: -


20 | 21 | ENDPOINT - http://localhost:8000/api/auth/register/ 22 |
23 | data = {
24 |     "name": "",
25 |     "phone_number": "",
26 |     "email": "",
27 |     "password": "",
28 |     "password2": ""
29 | }
30 | 


31 |

To login and authenticate into the API :


32 | 33 | ENDPOINT - http://localhost:8000/api/auth/login/
34 |
35 | data = {
36 |     "phone_number/email": "",
37 |     "password": "",
38 | }
39 | 

40 | Note :- I have used JWT Authentication and implicitly logging into django using login function, but for third party devices and apps, we can use token based system to verify and it has also been implemented here only
41 | After logging in you can use below ENDPOINTS 42 |

43 |

Search using the API


44 | ENDPOINT - http://localhost:8000/api/data/
45 |

46 | To search using a phone number -
47 | ENDPOINT - http://localhost:8000/api/data/?p={phone_number}
48 | 49 | Replace {phone_number} with phone number and make a get request 50 |

51 | To search using a name -
52 | ENDPOINT - http://localhost:8000/api/data/?name={name}
53 |
54 | Replace {phone_number} with phone number and make a get request
55 |

56 |

Detail View of Users

57 | ENDPOINT - http://localhost:8000/api/data/{user_id}
58 | 59 | Replace {user_id} with respective id of user to display.
60 | It has been keeping in mind to show the Email if Requested User has logged in user's phone number as a contact
61 |
62 | To mark spam 63 | Make a POST request to the ENDPOINT 64 |

65 |

Detail View of Contacts


66 | ENDPOINT - http://localhost:8000/api/data/p/{user_id}/ 67 |
68 | Replace {user_id} with respective id of user to display.
69 | It has been keeping in mind to show the Email if Requested User has logged in user's phone number as a contact 70 |
71 | To mark spam
72 | Make a POST request to the ENDPOINT
73 | 74 | 75 |

Declaration - This application is intended for educational purposes only. Any use in professional manner or to harm anyone or any organization doesn't relate to me and can be considered as illegal.

76 | 77 | 78 | Promotion - If you are lookingfor best instagram captions for your instagram posts then must check out Instafbcaptions.com 79 | -------------------------------------------------------------------------------- /accounts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__init__.py -------------------------------------------------------------------------------- /accounts/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/forms.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/forms.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib import admin 3 | from django.contrib.auth.models import Group 4 | from django.contrib.auth.admin import UserAdmin as BaseUserAdmin 5 | from django.contrib.auth.forms import ReadOnlyPasswordHashField 6 | from .models import MyUser 7 | from .forms import UserChangeForm, UserCreationForm 8 | 9 | 10 | 11 | class UserAdmin(BaseUserAdmin): 12 | form = UserChangeForm 13 | add_form = UserCreationForm 14 | list_display = ('name', 'phone_number', 'is_admin') 15 | list_filter = ('is_admin',) 16 | fieldsets = ( 17 | (None, {'fields': ('name', 'phone_number', 'password')}), 18 | ('Personal info', {'fields': ('email','spam_count')}), 19 | ('Permissions', {'fields': ('is_admin','is_staff')}), 20 | ) 21 | # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin 22 | # overrides get_fieldsets to use this attribute when creating a user. 23 | add_fieldsets = ( 24 | (None, { 25 | 'classes': ('wide',), 26 | 'fields': ('name', 'phone_number', 'email','password1', 'password2')} 27 | ), 28 | ) 29 | search_fields = ('phone_number', 'phone_number',) 30 | ordering = ('name', 'phone_number',) 31 | filter_horizontal = () 32 | 33 | 34 | 35 | 36 | 37 | admin.site.register(MyUser, UserAdmin) 38 | admin.site.unregister(Group) -------------------------------------------------------------------------------- /accounts/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__init__.py -------------------------------------------------------------------------------- /accounts/api/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/api/__pycache__/permissions.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/permissions.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/api/__pycache__/serializers.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/serializers.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/api/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/api/__pycache__/utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/utils.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/api/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/api/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/api/permissions.py: -------------------------------------------------------------------------------- 1 | from rest_framework import permissions 2 | 3 | class AnonPermissionOnly(permissions.BasePermission): 4 | def has_permission(self,request,view): 5 | return not request.user.is_authenticated -------------------------------------------------------------------------------- /accounts/api/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from django.contrib.auth import get_user_model 3 | import datetime 4 | from django.conf import settings 5 | from django.utils import timezone 6 | 7 | 8 | # token expires after a period of EXPIRATION_DELTA 9 | expire_delta = settings.JWT_AUTH['JWT_REFRESH_EXPIRATION_DELTA'] 10 | 11 | # JWT configuration to use 12 | from rest_framework_jwt.settings import api_settings 13 | jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER 14 | jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER 15 | jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER 16 | 17 | # instance of user model 18 | User = get_user_model() 19 | 20 | # Registeration Serializer 21 | class UserRegisterSerializer(serializers.ModelSerializer): 22 | password = serializers.CharField(style={'input_type':'password'},write_only=True) 23 | password2 = serializers.CharField(style={'input_type':'password'},write_only=True) 24 | token = serializers.SerializerMethodField(read_only=True) 25 | expires = serializers.SerializerMethodField(read_only=True) 26 | message = serializers.SerializerMethodField(read_only=True) 27 | 28 | class Meta: 29 | model=User 30 | fields=[ 31 | 'name', 32 | 'phone_number', 33 | 'email', 34 | 'password', 35 | 'password2', 36 | 'token', 37 | 'expires', 38 | 'message' 39 | ] 40 | def validate_phone_number(self,value): 41 | qs = User.objects.filter(phone_number__iexact=value) 42 | import re 43 | if not re.match("\d{10}",value): 44 | raise serializers.ValidationError("Enter a valid phone number") 45 | if qs.exists(): 46 | raise serializers.ValidationError("User with this phone number already exists") 47 | return value 48 | def get_message(self,obj): 49 | return "Registeration Successfull. To login go to /api/auth/" 50 | def get_expires(self,obj): 51 | return timezone.now() + expire_delta - datetime.timedelta(seconds=200) 52 | 53 | def get_token(self, obj): 54 | payload=jwt_payload_handler(obj) 55 | token=jwt_encode_handler(payload) 56 | return token 57 | def validate(self,data): 58 | pw = data.get("password") 59 | pw2 = data.pop("password2") 60 | if pw!= pw2: 61 | raise serializers.ValidationError("Passwords must match") 62 | return data 63 | 64 | -------------------------------------------------------------------------------- /accounts/api/urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework_jwt.views import obtain_jwt_token,refresh_jwt_token 2 | from django.urls import path 3 | from .views import AuthView,RegisterAPIView,LogoutAPIView 4 | 5 | urlpatterns = [ 6 | path('login/', AuthView.as_view()), 7 | path('register/', RegisterAPIView.as_view()), 8 | path('logout/', LogoutAPIView.as_view()), 9 | path('jwt/', obtain_jwt_token), 10 | path('refresh/', refresh_jwt_token), 11 | ] 12 | 13 | -------------------------------------------------------------------------------- /accounts/api/utils.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from django.conf import settings 3 | from django.utils import timezone 4 | from rest_framework_jwt.settings import api_settings 5 | expire_delta = settings.JWT_AUTH['JWT_REFRESH_EXPIRATION_DELTA'] 6 | 7 | def jwt_response_payload_handler(token,user=None,request=None): 8 | return { 9 | 'token':token, 10 | 'user':user.name, 11 | 'phone_number':user.phone_number, 12 | 'expires': timezone.now() + expire_delta - datetime.timedelta(seconds=200) 13 | } -------------------------------------------------------------------------------- /accounts/api/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import authenticate, get_user_model 2 | from django.db.models import Q 3 | from django.contrib.auth import logout,login 4 | 5 | # rest_framework 6 | from rest_framework import permissions, generics 7 | from rest_framework.views import APIView 8 | from rest_framework.response import Response 9 | 10 | # relative imports 11 | from .serializers import UserRegisterSerializer 12 | from .permissions import AnonPermissionOnly 13 | 14 | # jwt handlers 15 | from rest_framework_jwt.settings import api_settings 16 | jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER 17 | jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER 18 | jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER 19 | 20 | # User model 21 | User=get_user_model() 22 | 23 | # Login ENDPOINT Handler 24 | class AuthView(APIView): 25 | permission_classes = [permissions.AllowAny] 26 | def post(self, request, *args, **kwargs): 27 | if request.user.is_authenticated: 28 | return Response({"data":"You are already authenticated"}) 29 | data=request.data 30 | query=data.get("phone_number") 31 | password=data.get("password") 32 | qs=User.objects.filter( 33 | Q(phone_number__iexact=query)| 34 | Q(email__iexact=query) 35 | ).distinct() 36 | if qs.count()==1: 37 | user_obj=qs.first() 38 | if user_obj.check_password(password): 39 | user=user_obj 40 | login(request,user) 41 | payload=jwt_payload_handler(user) 42 | token=jwt_encode_handler(payload) 43 | response=jwt_response_payload_handler(token,user,request=request) 44 | return Response(response) 45 | return Response({"data":"Invalid Credentials"},status=401).add_post_render_callback 46 | 47 | # Register ENDPOINT Handler 48 | class RegisterAPIView(generics.CreateAPIView): 49 | queryset = User.objects.all() 50 | serializer_class = UserRegisterSerializer 51 | permission_classes = [AnonPermissionOnly] 52 | 53 | def get_serializer_context(self, *args,**kwargs): 54 | return {"request": self.request} 55 | 56 | # Logout ENDPOINT Handler 57 | class LogoutAPIView(APIView): 58 | def post(self,request,*args,**kwargs): 59 | logout(request) 60 | return Response({"Message":"Successfully Logged out"},status=200) -------------------------------------------------------------------------------- /accounts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountsConfig(AppConfig): 5 | name = 'accounts' 6 | -------------------------------------------------------------------------------- /accounts/forms.py: -------------------------------------------------------------------------------- 1 | # imports from django 2 | from django.db.models import Q 3 | from django import forms 4 | from django.contrib.auth.forms import ReadOnlyPasswordHashField 5 | from django.contrib.auth import get_user_model, authenticate 6 | from django.core.validators import RegexValidator 7 | 8 | # instance of User model 9 | User=get_user_model() 10 | 11 | # creating login form for user 12 | class UserLoginForm(forms.Form): 13 | phone_number=forms.CharField(label='Phone Number/Email',widget=forms.TextInput(attrs= 14 | { 15 | 'class':'form-control', 16 | 'placeholder' : 'User Name', 17 | })) 18 | password = forms.CharField(label='Password', widget=forms.PasswordInput(attrs= 19 | { 20 | 'class':'form-control', 21 | 'placeholder' : 'Password', 22 | })) 23 | # overriding default clean method for validating whether user and password are appropriate 24 | def clean(self, *args,**kwargs): 25 | query =self.cleaned_data.get('query') 26 | password =self.cleaned_data.get('password') 27 | user_qs_final=User.objects.filter( 28 | Q(phone_number__iexact=query)| 29 | Q(email__iexact=query) 30 | ).distinct() 31 | if not user_qs_final.exists() and user_qs_final.count() !=1: 32 | raise forms.ValidationError("Invalid Phone Number or Email") 33 | else: 34 | user_obj =user_qs_final.first() 35 | if not user_obj.check_password(password): 36 | raise forms.ValidationError("Invalid Password for {}".format(query)) 37 | self.cleaned_data['user_obj']=user_obj 38 | return super(UserLoginForm, self).clean(*args,**kwargs) 39 | 40 | #user creation form or in specific registeration form 41 | class UserCreationForm(forms.ModelForm): 42 | """A form for creating new users. Includes all the required 43 | fields, plus a repeated password.""" 44 | name = forms.CharField(label='Full Name') 45 | phone_number = forms.CharField() 46 | email = forms.EmailField(required=False) 47 | password1 = forms.CharField(label='Password', widget=forms.PasswordInput(attrs= 48 | { 49 | 'class':'form-control', 50 | 'placeholder' : 'Password', 51 | })) 52 | password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput(attrs= 53 | { 54 | 'class':'form-control', 55 | 'placeholder' : 'Confirm Password', 56 | })) 57 | 58 | class Meta: 59 | model = User 60 | fields = ('name','phone_number','email',) 61 | 62 | def clean_password2(self): 63 | # Check that the two password entries match 64 | password1 = self.cleaned_data.get("password1") 65 | password2 = self.cleaned_data.get("password2") 66 | if len(password1)<7: 67 | raise forms.ValidationError("Password must be of at least 8 digits") 68 | 69 | if password1 and password2 and password1 != password2: 70 | raise forms.ValidationError("Passwords don't match") 71 | return password2 72 | 73 | def save(self, commit=True): 74 | # Save the provided password in hashed format 75 | user = super().save(commit=False) 76 | user.set_password(self.cleaned_data["password1"]) 77 | if commit: 78 | user.save() 79 | return user 80 | 81 | # changing the user from admin panel itself 82 | class UserChangeForm(forms.ModelForm): 83 | password = ReadOnlyPasswordHashField() 84 | 85 | class Meta: 86 | model = User 87 | fields = ('name', 'phone_number', 'email', 'spam_count','is_staff', 'is_admin','password') 88 | 89 | def clean_password(self): 90 | # Regardless of what the user provides, return the initial value. 91 | # This is done here, rather than on the field, because the 92 | # field does not have access to the initial value 93 | return self.initial["password"] -------------------------------------------------------------------------------- /accounts/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.7 on 2019-11-27 13:41 2 | 3 | import django.core.validators 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='MyUser', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('password', models.CharField(max_length=128, verbose_name='password')), 20 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), 21 | ('name', models.CharField(max_length=120)), 22 | ('phone_number', models.CharField(max_length=20, unique=True, validators=[django.core.validators.RegexValidator(code='invalid_username', message='Phone Number must be of 10 digits', regex='^[0-9]*{10}$')])), 23 | ('email', models.EmailField(blank=True, max_length=255, null=True, unique=True, verbose_name='email address')), 24 | ('is_admin', models.BooleanField(default=False)), 25 | ('is_staff', models.BooleanField(default=False)), 26 | ], 27 | options={ 28 | 'abstract': False, 29 | }, 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /accounts/migrations/0002_auto_20191127_1345.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.7 on 2019-11-27 13:45 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('accounts', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='myuser', 15 | name='email', 16 | field=models.EmailField(blank=True, max_length=255, null=True, verbose_name='email address'), 17 | ), 18 | migrations.AlterField( 19 | model_name='myuser', 20 | name='phone_number', 21 | field=models.CharField(max_length=20, unique=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /accounts/migrations/0003_myuser_spam_count.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.7 on 2019-11-27 21:20 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('accounts', '0002_auto_20191127_1345'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='myuser', 15 | name='spam_count', 16 | field=models.IntegerField(default=0), 17 | preserve_default=False, 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /accounts/migrations/0004_auto_20191127_2121.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.7 on 2019-11-27 21:21 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('accounts', '0003_myuser_spam_count'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='myuser', 15 | name='spam_count', 16 | field=models.IntegerField(default=0), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /accounts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__init__.py -------------------------------------------------------------------------------- /accounts/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/migrations/__pycache__/0002_auto_20191127_1345.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/0002_auto_20191127_1345.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/migrations/__pycache__/0003_myuser_spam_count.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/0003_myuser_spam_count.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/migrations/__pycache__/0004_auto_20191127_2121.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/0004_auto_20191127_2121.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.db import models 3 | from django.db.models.signals import post_save 4 | from django.contrib.auth.models import ( 5 | BaseUserManager, AbstractBaseUser 6 | ) 7 | from django.core.validators import RegexValidator 8 | 9 | 10 | class MyUserManager(BaseUserManager): 11 | def create_user(self, name, phone_number, email, password=None): 12 | """ 13 | Creates and saves a User with the given phone number, name and password 14 | """ 15 | if not phone_number: 16 | raise ValueError('User must have a Phone Number') 17 | if not email: 18 | email="" 19 | else: 20 | email=self.normalize_email(email), 21 | 22 | user = self.model( 23 | name=name, 24 | phone_number=phone_number, 25 | email=email, 26 | ) 27 | 28 | user.set_password(password) 29 | user.save(using=self._db) 30 | return user 31 | 32 | def create_superuser(self, name, phone_number, password): 33 | """ 34 | Creates and saves a superuser with the given email, date of 35 | birth and password. 36 | """ 37 | email="" 38 | user = self.create_user( 39 | name, 40 | phone_number, 41 | email, 42 | password=password, 43 | ) 44 | user.is_admin = True 45 | user.is_staff = True 46 | user.save(using=self._db) 47 | return user 48 | 49 | NAME_REGEX='^[a-zA-Z]*$' 50 | PHONENO_REGEX='^[0-9]*{10}$' 51 | 52 | # overriding default USER MODEL 53 | class MyUser(AbstractBaseUser): 54 | name=models.CharField(max_length=120) 55 | phone_number = models.CharField(max_length=20, 56 | unique=True) 57 | email = models.EmailField( 58 | verbose_name='email address', 59 | max_length=255, 60 | null=True, 61 | blank=True 62 | ) 63 | spam_count = models.IntegerField(default=0) 64 | is_admin = models.BooleanField(default=False) 65 | is_staff = models.BooleanField(default=False) 66 | objects = MyUserManager() 67 | USERNAME_FIELD = 'phone_number' 68 | REQUIRED_FIELDS = ['name'] 69 | 70 | def __str__(self): 71 | return self.name 72 | 73 | def has_perm(self, perm, obj=None): 74 | "Does the user have a specific permission?" 75 | # Simplest possible answer: Yes, always 76 | return True 77 | def has_module_perms(self, app_label): 78 | "Does the user have permissions to view the app `app_label`?" 79 | # Simplest possible answer: Yes, always 80 | return True -------------------------------------------------------------------------------- /accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /accounts/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path,include 2 | 3 | 4 | urlpatterns = [ 5 | path('', include("accounts.api.urls")), 6 | ] 7 | -------------------------------------------------------------------------------- /accounts/views.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/accounts/views.py -------------------------------------------------------------------------------- /data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__init__.py -------------------------------------------------------------------------------- /data/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /data/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /data/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /data/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /data/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /data/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | from .models import PersonalContacts 5 | 6 | admin.site.register(PersonalContacts) -------------------------------------------------------------------------------- /data/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__init__.py -------------------------------------------------------------------------------- /data/api/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /data/api/__pycache__/serializers.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__pycache__/serializers.cpython-36.pyc -------------------------------------------------------------------------------- /data/api/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /data/api/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/api/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /data/api/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from django.contrib.auth import get_user_model 3 | from data.models import PersonalContacts 4 | User = get_user_model() 5 | 6 | # To display user model search results 7 | class UserModelSerializer(serializers.ModelSerializer): 8 | uri = serializers.SerializerMethodField(read_only=True) 9 | class Meta: 10 | model=User 11 | fields=[ 12 | 'uri', 13 | 'name', 14 | 'phone_number', 15 | 'spam_count' 16 | ] 17 | def get_uri(self,obj): 18 | return "http://localhost:8000/api/data/{}/".format(obj.id) 19 | 20 | # To display personal_contacts model search results 21 | class PersonalContactsSerializer(serializers.ModelSerializer): 22 | uri = serializers.SerializerMethodField(read_only=True) 23 | class Meta: 24 | model=PersonalContacts 25 | fields=[ 26 | 'uri', 27 | 'name', 28 | 'phone_number', 29 | 'spam_count' 30 | ] 31 | def get_uri(self,obj): 32 | return "http://localhost:8000/api/data/p/{}/".format(obj.id) 33 | 34 | -------------------------------------------------------------------------------- /data/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from .views import ( 3 | DataListSearchAPIView, 4 | UserDetailAPIView, 5 | PersonalContactsDetailAPIView 6 | # UserMarkSpamAPIView 7 | 8 | ) 9 | 10 | urlpatterns = [ 11 | path('', DataListSearchAPIView.as_view()), 12 | path('/', UserDetailAPIView.as_view()), 13 | path('p//', PersonalContactsDetailAPIView.as_view()), 14 | 15 | # path('/spam', UserMarkSpamAPIView.as_view()), 16 | 17 | ] 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /data/api/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import get_user_model 2 | from django.db.models import Q 3 | User=get_user_model() 4 | 5 | # rest_framework 6 | from rest_framework import permissions, generics, mixins 7 | from rest_framework.views import APIView 8 | from rest_framework.response import Response 9 | 10 | # relative import of serializer 11 | from .serializers import UserModelSerializer, PersonalContactsSerializer 12 | 13 | # importing Model 14 | from data.models import PersonalContacts 15 | 16 | # Search View Handler API ENDPOINT 17 | class DataListSearchAPIView(APIView): 18 | def get(self,request,*args, **kwargs): 19 | if 'p' in request.GET: 20 | search_phone_number = request.GET['p'] 21 | qs = User.objects.filter(phone_number__iexact=search_phone_number) 22 | if qs.count()==1: 23 | serializer = UserModelSerializer(qs, many=True) 24 | return Response(serializer.data) 25 | else: 26 | qs = PersonalContacts.objects.filter(phone_number__iexact=search_phone_number) 27 | print(qs) 28 | if qs.count() > 0: 29 | serializer = PersonalContactsSerializer(qs, many=True) 30 | data={ 31 | "message":"Number is not registered", 32 | "data":serializer.data 33 | } 34 | return Response(data) 35 | if 'name' in request.GET: 36 | search_name = request.GET['name'] 37 | user_qs = User.objects.filter( 38 | Q(name__startswith=search_name)| 39 | Q(name__icontains = search_name) 40 | ).distinct() 41 | p_qs = PersonalContacts.objects.filter( 42 | Q(name__startswith=search_name)| 43 | Q(name__icontains = search_name) 44 | ).distinct() 45 | serializer1 = UserModelSerializer(user_qs,many=True) 46 | serializer2 = PersonalContactsSerializer(p_qs, many=True) 47 | data={ 48 | 'registered_users':serializer1.data, 49 | 'personal_contacts':serializer2.data 50 | } 51 | return Response(data) 52 | return Response({"data":"Search something by name (?name=) or phone_number (?p=)"},status=200) 53 | 54 | # detail view of User model 55 | class UserDetailAPIView(APIView): 56 | 57 | def get(self,request,pk,*args,**kwargs): 58 | qs=User.objects.get(id=pk) 59 | serializer = UserModelSerializer(qs) 60 | 61 | # to display email or not 62 | # user is already registered 63 | # now check whether searching user is in this user's contact list 64 | check_qs = PersonalContacts.objects.filter( 65 | Q(user=qs) & 66 | Q(phone_number__icontains=request.user.phone_number) 67 | ) 68 | if check_qs.count()>0: 69 | data={ 70 | "data":serializer.data, 71 | "email":qs.email 72 | } 73 | else: 74 | data=serializer.data 75 | return Response(data) 76 | 77 | def post(self,request,pk,*args,**kwargs): 78 | q=User.objects.get(id=pk) 79 | q.spam_count+=1 80 | q.save() 81 | serializer = UserModelSerializer(q) 82 | data={ 83 | "data":serializer.data, 84 | "message":"{} marked as spam.".format(q.name) 85 | } 86 | return Response(data,status=200) 87 | 88 | 89 | # detail view of Personal contacts model 90 | class PersonalContactsDetailAPIView(APIView): 91 | 92 | def get(self,request,pk,*args,**kwargs): 93 | qs=PersonalContacts.objects.get(id=pk) 94 | serializer = PersonalContactsSerializer(qs) 95 | return Response(serializer.data) 96 | 97 | def post(self,request,pk,*args,**kwargs): 98 | q=PersonalContacts.objects.get(id=pk) 99 | q.spam_count+=1 100 | q.save() 101 | serializer = PersonalContactsSerializer(q) 102 | data={ 103 | "data":serializer.data, 104 | "message":"{} marked as spam.".format(q.name) 105 | } 106 | return Response(data,status=200) 107 | -------------------------------------------------------------------------------- /data/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class DataConfig(AppConfig): 5 | name = 'data' 6 | -------------------------------------------------------------------------------- /data/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.7 on 2019-11-27 21:22 2 | 3 | from django.conf import settings 4 | import django.core.validators 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name='PersonalContacts', 20 | fields=[ 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('name', models.CharField(max_length=200)), 23 | ('phone_number', models.CharField(max_length=200, validators=[django.core.validators.RegexValidator(code='invalid_username', message='Phone Number must be of 10 digits', regex='^[0-9]*$')])), 24 | ('email_address', models.EmailField(max_length=254)), 25 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 26 | ], 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /data/migrations/0002_auto_20191127_2150.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.7 on 2019-11-27 21:50 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='personalcontacts', 15 | name='spam_count', 16 | field=models.IntegerField(default=0), 17 | ), 18 | migrations.AlterField( 19 | model_name='personalcontacts', 20 | name='email_address', 21 | field=models.EmailField(blank=True, max_length=254, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /data/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/migrations/__init__.py -------------------------------------------------------------------------------- /data/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /data/migrations/__pycache__/0002_auto_20191127_2150.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/migrations/__pycache__/0002_auto_20191127_2150.cpython-36.pyc -------------------------------------------------------------------------------- /data/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/data/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /data/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.core.validators import RegexValidator 3 | from django.conf import settings 4 | # Create your models here. 5 | 6 | PHONENO_REGEX='^[0-9]{10}$' 7 | 8 | class PersonalContacts(models.Model): 9 | user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE) 10 | name = models.CharField(max_length=200) 11 | phone_number = models.CharField(max_length=200,validators=[RegexValidator( 12 | regex=PHONENO_REGEX, 13 | message="Phone Number must be of 10 digits", 14 | code='invalid_username' 15 | )]) 16 | email_address = models.EmailField(null=True, blank=True) 17 | spam_count = models.IntegerField(default=0) 18 | def __str__(self): 19 | return self.name -------------------------------------------------------------------------------- /data/templates/home.html: -------------------------------------------------------------------------------- 1 | This is a brief description of what this app does and how these apis work
2 | As specified, this app is just like truecaller and works on same principle
3 | 4 | To start the project, one needs to run the server first using the specified virtual environment.
5 | On Linux,
6 | Enter following commands once you are in this directory
7 |
 8 |     source venv/bin/activate 
 9 |     cd truecaller
10 |     python manage.py runserver
11 | 
12 | Now the application server has started,

13 | 14 |

Every Functionality implemented in the code could have been implemented using various other methods. I have used methods which I felt would be appropriate

15 | To access anything in the api , one needs to be logged in otherwise it will raise Authentication errors.

16 | 17 |

To register using the API: -


18 | 19 | ENDPOINT - http://localhost:8000/api/auth/register/ 20 |
21 | data = {
22 |     "name": "",
23 |     "phone_number": "",
24 |     "email": "",
25 |     "password": "",
26 |     "password2": ""
27 | }
28 | 


29 |

To login and authenticate into the API :


30 | 31 | ENDPOINT - http://localhost:8000/api/auth/login/
32 |
33 | data = {
34 |     "phone_number/email": "",
35 |     "password": "",
36 | }
37 | 

38 | Note :- I have used JWT Authentication and implicitly logging into django using login function, but for third party devices and apps, we can use token based system to verify and it has also been implemented here only
39 | After logging in you can use below ENDPOINTS 40 |

41 |

Search using the API


42 | ENDPOINT - http://localhost:8000/api/data/
43 |

44 | To search using a phone number -
45 | ENDPOINT - http://localhost:8000/api/data/?p={phone_number}
46 | 47 | Replace {phone_number} with phone number and make a get request 48 |

49 | To search using a name -
50 | ENDPOINT - http://localhost:8000/api/data/?name={name}
51 |
52 | Replace {phone_number} with phone number and make a get request
53 |

54 |

Detail View of Users

55 | ENDPOINT - http://localhost:8000/api/data/{user_id}
56 | 57 | Replace {user_id} with respective id of user to display.
58 | It has been keeping in mind to show the Email if Requested User has logged in user's phone number as a contact
59 |
60 | To mark spam 61 | Make a POST request to the ENDPOINT 62 |

63 |

Detail View of Contacts


64 | ENDPOINT - http://localhost:8000/api/data/p/{user_id}/ 65 |
66 | Replace {user_id} with respective id of user to display.
67 | It has been keeping in mind to show the Email if Requested User has logged in user's phone number as a contact 68 |
69 | To mark spam
70 | Make a POST request to the ENDPOINT
71 | 72 | 73 |

Declaration - This application is intended for use by reciepent only. Any use in professional manner or to harm anyone or any organization doesn't relate to me and can be considered as illegal.

-------------------------------------------------------------------------------- /data/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /data/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | from .views import home_view 3 | urlpatterns = [ 4 | path('', home_view), 5 | path('api/data/', include("data.api.urls")), 6 | 7 | ] 8 | -------------------------------------------------------------------------------- /data/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | def home_view(request): 5 | return render(request,"home.html") -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/db.sqlite3 -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'truecaller.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2019.9.11 2 | chardet==3.0.4 3 | Django==2.2.8 4 | django-filter==2.2.0 5 | djangorestframework==3.10.3 6 | djangorestframework-jwt==1.11.0 7 | idna==2.8 8 | Markdown==3.1.1 9 | PyJWT==1.7.1 10 | pytz==2019.3 11 | requests==2.22.0 12 | sqlparse==0.3.0 13 | urllib3==1.25.7 14 | -------------------------------------------------------------------------------- /truecaller/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__init__.py -------------------------------------------------------------------------------- /truecaller/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /truecaller/__pycache__/putdata.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/putdata.cpython-36.pyc -------------------------------------------------------------------------------- /truecaller/__pycache__/settings.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/settings.cpython-36.pyc -------------------------------------------------------------------------------- /truecaller/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /truecaller/__pycache__/wsgi.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/__pycache__/wsgi.cpython-36.pyc -------------------------------------------------------------------------------- /truecaller/data.csv: -------------------------------------------------------------------------------- 1 | Mobile_Number,Name,Email 2 | 917053000273,Sunita, 3 | 917053001487,Shobhit, 4 | 917053001479,Govind Govind,singhgovind01420@gmail.com 5 | 917053001460,Arman Khan, 6 | 917053001433,Sandhya Sharma, 7 | 917053001432,Rahul Sharma,rahul.sharma.71.rs@gmail.com 8 | 917053001422,Manoj Kumar,manojprajapati7053@gmail.com 9 | 917053001413,Ail Abid,aliabid47422@gmail.com 10 | 917053001410,Preeti Sain,preetisain241996@gmail.com 11 | 917053001378,Abhishek Verma,abhishek.nature16@gmail.com 12 | 917053001347,Chulbul Pandey, 13 | 917053001343,Armaan Ali,manjeetroy7867@gmail.com 14 | 917053001334,Anuj Rai Spice Jet, 15 | 917053001333,Kishan Singh, 16 | 917053001319,Mamtesh Sharma,uditupadhyay29@gmail.com 17 | 917053001314,Ajay K,ajayk.kumar91@gmail.com 18 | 917053001312,Alok Singh, 19 | 917053001300,Abhishek Sharma (kush Pandit), 20 | 917053001298,Cma Neeraj, 21 | 917053001297,Suresh Pal,suresh.pal0707@gmail.com 22 | 917053001268,Shailendra Singh,shailendrasbscet@gmail.com 23 | 917053001250,Rohit, 24 | 917053001244,Vipin Shop, 25 | 917053001209,Keshav Jha,keshavkrjha149@gmail.com 26 | 917053001207,Nidhi, 27 | 917053001199,Sachin Sanjay Enclave, 28 | 917053001193,Pradeep Das,pradeepdas180@gmail.com 29 | 917053001170,Cma Shalini, 30 | 917053001153,Soma Raj, 31 | 917053001147,Rajeev Kumar,rbrajeevkumar005@gmail.com 32 | 917053001139,Indu, 33 | 917053001133,Abhay Singh,abhay28singh@gmail.com 34 | 917053001128,Golu Kk, 35 | 917053001113,Dayaram Choraai, 36 | 917053001109,Roshan, 37 | 917053001101,Kapil, 38 | 917053001069,Naina Ranjna, 39 | 917053001064,Vishal Chaturvedi, 40 | 917053001045,Rishi Trolley, 41 | 917053001037,Sudhirkumar Sudhirkumar, 42 | 917053001019,Sumit Kumar,sumitkumard1671985@gmail.com 43 | 917053001008,Aniket, 44 | 917053001003,Basant Kumar, 45 | 917053001002,Papa G,yoginderkmr18@gmail.com 46 | 917053000980,Kamal Kashyap,kamalkashyap4000@gmail.com 47 | 917053000976,Aircel977 Delm977, 48 | 917053000942,Pankaj Office Larka, 49 | 917053000938,Preeti Singh, 50 | 917053000936,Satya Parkash Prasad,iipl.satyaparkash@gmail.com 51 | 917053000912,Vidhi, 52 | 917053000909,Sikka Pardhan, 53 | 917053000908,Dagar Shab, 54 | 917053000894,Miister Potterhead, 55 | 917053000888,Kamal Kamal, 56 | 917053000879,Ruby, 57 | 917053000868,India Gurgaon, 58 | 917053000858,Anand Driver, 59 | 917053000857,Barkte Hr, 60 | 917053000850,Mukesh, 61 | 917053000849,Salman Syed,mohdsksalman@gmail.com 62 | 917053000845,Ramkesh Gurjar Bainsla, 63 | 917053000840,Shweta Amarjeet Bhabhiji, 64 | 917053000836,Kundan Kumar,kumarkundan7053@gmail.com 65 | 917053000833,Gurucharan Singh, 66 | 917053000821,Rinki Bkp, 67 | 917053000819,Jagram Singh,jagramsingh63487@gmail.com 68 | 917053000808,Vijay Mcd, 69 | 917053000806,Samrat Guru, 70 | 917053000786,Gurgaon Airtel, 71 | 917053000780,Raju 2, 72 | 917053000777,Kamal Kamal,kamalkamalkamalkamal087@gmail.com 73 | 917053000768,Mr. Siddiqui, 74 | 917053000756,Pardeep Gujjar, 75 | 917053000751,Rakesh, 76 | 917053000750,Sumit Mama, 77 | 917053000743,Sameer Sameer, 78 | 917053000736,Sunder Khandiya,sunderkhandiyas@gmail.com 79 | 917053000727,Riya, 80 | 917053000702,Shadab Rangrezz, 81 | 917053000700,Aircel701 Delm701, 82 | 917053000688,Shruti 2, 83 | 917053000680,Nnnn. Khaan, 84 | 917053000678,Amrik Singh,amriks841@gmail.com 85 | 917053000672,Vaseem, 86 | 917053000666,Rishab Singh,6525jatin@gmail.com 87 | 917053000656,Rajender 3, 88 | 917053000648,Tinku, 89 | 917053000645,No Naah!!, 90 | 917053000619,Rajbala Mami, 91 | 917053000618,Tarun Ahuja,pals9992@gmail.com 92 | 917053000600,Aircel601 Delm601, 93 | 917053000594,Neetesh Kumar Raj, 94 | 917053000593,Chandra Ji Airport, 95 | -------------------------------------------------------------------------------- /truecaller/putdata.py: -------------------------------------------------------------------------------- 1 | 2 | def get_data(): 3 | import csv 4 | # csv file name 5 | filename = "data.csv" 6 | 7 | # initializing the titles and rows list 8 | fields = [] 9 | rows = [] 10 | 11 | # reading csv file 12 | with open(filename, 'r') as csvfile: 13 | # creating a csv reader object 14 | csvreader = csv.reader(csvfile) 15 | 16 | # extracting field names through first row 17 | fields = next(csvreader) 18 | 19 | # extracting each data row one by one 20 | for row in csvreader: 21 | rows.append(row) 22 | return fields,rows 23 | # printing first 5 rows 24 | print('\nFirst 5 rows are:\n') 25 | for row in rows[:5]: 26 | # parsing each column of a row 27 | for col in row: 28 | print("%10s"%col), 29 | print('\n') -------------------------------------------------------------------------------- /truecaller/restconf/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/restconf/__init__.py -------------------------------------------------------------------------------- /truecaller/restconf/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/restconf/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /truecaller/restconf/__pycache__/main.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naveenkrnl/Truecaller-APIs/6aaf1f8083efc3af0a3580f845d980c80521def4/truecaller/restconf/__pycache__/main.cpython-36.pyc -------------------------------------------------------------------------------- /truecaller/restconf/main.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | REST_FRAMEWORK = { 3 | 'DEFAULT_AUTHENTICATION_CLASSES': ( 4 | 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 5 | 'rest_framework.authentication.SessionAuthentication', 6 | ), 7 | 'DEFAULT_PERMISSION_CLASSES':( 8 | 'rest_framework.permissions.IsAuthenticated', 9 | ) 10 | } 11 | 12 | JWT_AUTH = { 13 | 'JWT_ENCODE_HANDLER': 14 | 'rest_framework_jwt.utils.jwt_encode_handler', 15 | 16 | 'JWT_DECODE_HANDLER': 17 | 'rest_framework_jwt.utils.jwt_decode_handler', 18 | 19 | 'JWT_PAYLOAD_HANDLER': 20 | 'rest_framework_jwt.utils.jwt_payload_handler', 21 | 22 | 'JWT_PAYLOAD_GET_USER_ID_HANDLER': 23 | 'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler', 24 | 25 | 'JWT_RESPONSE_PAYLOAD_HANDLER': 26 | # 'rest_framework_jwt.utils.jwt_response_payload_handler', 27 | 'accounts.api.utils.jwt_response_payload_handler', 28 | 29 | 'JWT_ALLOW_REFRESH': True, 30 | 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7), 31 | 32 | 'JWT_AUTH_HEADER_PREFIX': 'JWT', 33 | 'JWT_AUTH_COOKIE': None, 34 | 35 | } -------------------------------------------------------------------------------- /truecaller/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for truecaller project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.2.7. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.2/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'hrpuk=3vgiqi=it*x+(g$fu7o%p%mjmpsg!_x$s$bnl7y7n22b' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | AUTH_USER_MODEL = 'accounts.MyUser' 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | # third-party 41 | 'rest_framework', 42 | 43 | # local 44 | 'data', 45 | 'accounts' 46 | ] 47 | 48 | MIDDLEWARE = [ 49 | 'django.middleware.security.SecurityMiddleware', 50 | 'django.contrib.sessions.middleware.SessionMiddleware', 51 | 'django.middleware.common.CommonMiddleware', 52 | 'django.middleware.csrf.CsrfViewMiddleware', 53 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 54 | 'django.contrib.messages.middleware.MessageMiddleware', 55 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 56 | ] 57 | 58 | ROOT_URLCONF = 'truecaller.urls' 59 | 60 | TEMPLATES = [ 61 | { 62 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 63 | 'DIRS': [], 64 | 'APP_DIRS': True, 65 | 'OPTIONS': { 66 | 'context_processors': [ 67 | 'django.template.context_processors.debug', 68 | 'django.template.context_processors.request', 69 | 'django.contrib.auth.context_processors.auth', 70 | 'django.contrib.messages.context_processors.messages', 71 | ], 72 | }, 73 | }, 74 | ] 75 | 76 | WSGI_APPLICATION = 'truecaller.wsgi.application' 77 | 78 | 79 | # Database 80 | # https://docs.djangoproject.com/en/2.2/ref/settings/#databases 81 | 82 | DATABASES = { 83 | 'default': { 84 | 'ENGINE': 'django.db.backends.sqlite3', 85 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 86 | } 87 | } 88 | 89 | 90 | # Password validation 91 | # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators 92 | 93 | AUTH_PASSWORD_VALIDATORS = [ 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 99 | }, 100 | { 101 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 102 | }, 103 | { 104 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 105 | }, 106 | ] 107 | 108 | 109 | # Internationalization 110 | # https://docs.djangoproject.com/en/2.2/topics/i18n/ 111 | 112 | LANGUAGE_CODE = 'en-us' 113 | 114 | TIME_ZONE = 'UTC' 115 | 116 | USE_I18N = True 117 | 118 | USE_L10N = True 119 | 120 | USE_TZ = True 121 | 122 | 123 | # Static files (CSS, JavaScript, Images) 124 | # https://docs.djangoproject.com/en/2.2/howto/static-files/ 125 | 126 | STATIC_URL = '/static/' 127 | 128 | from truecaller.restconf.main import * -------------------------------------------------------------------------------- /truecaller/urls.py: -------------------------------------------------------------------------------- 1 | """truecaller URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('api/auth/', include("accounts.urls")), 22 | path('', include("data.urls")), 23 | 24 | ] 25 | -------------------------------------------------------------------------------- /truecaller/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for truecaller project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'truecaller.settings') 15 | 16 | application = get_wsgi_application() 17 | --------------------------------------------------------------------------------